user_test.exs 31.5 KB
Newer Older
kaniini's avatar
kaniini committed
1
2
3
4
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only

lain's avatar
lain committed
5
6
defmodule Pleroma.UserTest do
  alias Pleroma.Builders.UserBuilder
Haelwenn's avatar
Haelwenn committed
7
8
9
  alias Pleroma.Activity
  alias Pleroma.Repo
  alias Pleroma.User
10
  alias Pleroma.Web.CommonAPI
lain's avatar
lain committed
11
12
  use Pleroma.DataCase

lain's avatar
lain committed
13
14
  import Pleroma.Factory

Maksim's avatar
Maksim committed
15
16
17
18
19
  setup_all do
    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
    :ok
  end

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  describe "when tags are nil" do
    test "tagging a user" do
      user = insert(:user, %{tags: nil})
      user = User.tag(user, ["cool", "dude"])

      assert "cool" in user.tags
      assert "dude" in user.tags
    end

    test "untagging a user" do
      user = insert(:user, %{tags: nil})
      user = User.untag(user, ["cool", "dude"])

      assert user.tags == []
    end
  end

lain's avatar
lain committed
37
  test "ap_id returns the activity pub id for the user" do
lain's avatar
lain committed
38
    user = UserBuilder.build()
lain's avatar
lain committed
39

lain's avatar
lain committed
40
    expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
lain's avatar
lain committed
41
42
43
44
45

    assert expected_ap_id == User.ap_id(user)
  end

  test "ap_followers returns the followers collection for the user" do
lain's avatar
lain committed
46
    user = UserBuilder.build()
lain's avatar
lain committed
47
48
49
50
51

    expected_followers_collection = "#{User.ap_id(user)}/followers"

    assert expected_followers_collection == User.ap_followers(user)
  end
lain's avatar
lain committed
52

lain's avatar
lain committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  test "returns all pending follow requests" do
    unlocked = insert(:user)
    locked = insert(:user, %{info: %{locked: true}})
    follower = insert(:user)

    Pleroma.Web.TwitterAPI.TwitterAPI.follow(follower, %{"user_id" => unlocked.id})
    Pleroma.Web.TwitterAPI.TwitterAPI.follow(follower, %{"user_id" => locked.id})

    assert {:ok, []} = User.get_follow_requests(unlocked)
    assert {:ok, [activity]} = User.get_follow_requests(locked)

    assert activity
  end

67
68
69
70
71
72
73
74
75
76
77
78
79
80
  test "doesn't return already accepted or duplicate follow requests" do
    locked = insert(:user, %{info: %{locked: true}})
    pending_follower = insert(:user)
    accepted_follower = insert(:user)

    Pleroma.Web.TwitterAPI.TwitterAPI.follow(pending_follower, %{"user_id" => locked.id})
    Pleroma.Web.TwitterAPI.TwitterAPI.follow(pending_follower, %{"user_id" => locked.id})
    Pleroma.Web.TwitterAPI.TwitterAPI.follow(accepted_follower, %{"user_id" => locked.id})
    User.maybe_follow(accepted_follower, locked)

    assert {:ok, [activity]} = User.get_follow_requests(locked)
    assert activity
  end

lain's avatar
lain committed
81
82
  test "follow_all follows mutliple users" do
    user = insert(:user)
lain's avatar
lain committed
83
    followed_zero = insert(:user)
lain's avatar
lain committed
84
85
    followed_one = insert(:user)
    followed_two = insert(:user)
lain's avatar
lain committed
86
    blocked = insert(:user)
lain's avatar
lain committed
87
    not_followed = insert(:user)
88
    reverse_blocked = insert(:user)
lain's avatar
lain committed
89

lain's avatar
lain committed
90
    {:ok, user} = User.block(user, blocked)
91
    {:ok, reverse_blocked} = User.block(reverse_blocked, user)
lain's avatar
lain committed
92

lain's avatar
lain committed
93
    {:ok, user} = User.follow(user, followed_zero)
lain's avatar
lain committed
94

95
    {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
lain's avatar
lain committed
96
97
98

    assert User.following?(user, followed_one)
    assert User.following?(user, followed_two)
lain's avatar
lain committed
99
100
    assert User.following?(user, followed_zero)
    refute User.following?(user, not_followed)
lain's avatar
lain committed
101
    refute User.following?(user, blocked)
102
    refute User.following?(user, reverse_blocked)
lain's avatar
lain committed
103
104
  end

105
106
107
108
109
110
111
112
113
114
115
116
117
  test "follow_all follows mutliple users without duplicating" do
    user = insert(:user)
    followed_zero = insert(:user)
    followed_one = insert(:user)
    followed_two = insert(:user)

    {:ok, user} = User.follow_all(user, [followed_zero, followed_one])
    assert length(user.following) == 3

    {:ok, user} = User.follow_all(user, [followed_one, followed_two])
    assert length(user.following) == 4
  end

lain's avatar
lain committed
118
  test "follow takes a user and another user" do
lain's avatar
lain committed
119
120
    user = insert(:user)
    followed = insert(:user)
lain's avatar
lain committed
121

lain's avatar
lain committed
122
    {:ok, user} = User.follow(user, followed)
lain's avatar
lain committed
123
124
125

    user = Repo.get(User, user.id)

126
    followed = User.get_by_ap_id(followed.ap_id)
lain's avatar
lain committed
127
    assert followed.info.follower_count == 1
128

129
    assert User.ap_followers(followed) in user.following
lain's avatar
lain committed
130
  end
lain's avatar
lain committed
131

lain's avatar
lain committed
132
133
  test "can't follow a deactivated users" do
    user = insert(:user)
lain's avatar
lain committed
134
    followed = insert(:user, info: %{deactivated: true})
lain's avatar
lain committed
135
136
137
138

    {:error, _} = User.follow(user, followed)
  end

139
140
141
142
143
144
145
146
147
  test "can't follow a user who blocked us" do
    blocker = insert(:user)
    blockee = insert(:user)

    {:ok, blocker} = User.block(blocker, blockee)

    {:error, _} = User.follow(blockee, blocker)
  end

kaniini's avatar
kaniini committed
148
  test "local users do not automatically follow local locked accounts" do
lain's avatar
lain committed
149
150
    follower = insert(:user, info: %{locked: true})
    followed = insert(:user, info: %{locked: true})
kaniini's avatar
kaniini committed
151
152
153
154
155
156

    {:ok, follower} = User.maybe_direct_follow(follower, followed)

    refute User.following?(follower, followed)
  end

lain's avatar
lain committed
157
158
159
160
  # This is a somewhat useless test.
  # test "following a remote user will ensure a websub subscription is present" do
  #   user = insert(:user)
  #   {:ok, followed} = OStatus.make_user("shp@social.heldscal.la")
lain's avatar
lain committed
161

lain's avatar
lain committed
162
  #   assert followed.local == false
lain's avatar
lain committed
163

lain's avatar
lain committed
164
165
  #   {:ok, user} = User.follow(user, followed)
  #   assert User.ap_followers(followed) in user.following
lain's avatar
lain committed
166

lain's avatar
lain committed
167
168
169
  #   query = from w in WebsubClientSubscription,
  #   where: w.topic == ^followed.info["topic"]
  #   websub = Repo.one(query)
lain's avatar
lain committed
170

lain's avatar
lain committed
171
172
  #   assert websub
  # end
lain's avatar
lain committed
173

lain's avatar
lain committed
174
  test "unfollow takes a user and another user" do
lain's avatar
lain committed
175
176
    followed = insert(:user)
    user = insert(:user, %{following: [User.ap_followers(followed)]})
lain's avatar
lain committed
177

lain's avatar
lain committed
178
    {:ok, user, _activity} = User.unfollow(user, followed)
lain's avatar
lain committed
179
180
181
182
183

    user = Repo.get(User, user.id)

    assert user.following == []
  end
184

185
186
187
188
189
  test "unfollow doesn't unfollow yourself" do
    user = insert(:user)

    {:error, _} = User.unfollow(user, user)

eal's avatar
eal committed
190
    user = Repo.get(User, user.id)
191
192
193
    assert user.following == [user.ap_id]
  end

194
  test "test if a user is following another user" do
lain's avatar
lain committed
195
196
    followed = insert(:user)
    user = insert(:user, %{following: [User.ap_followers(followed)]})
197
198
199
200

    assert User.following?(user, followed)
    refute User.following?(followed, user)
  end
lain's avatar
lain committed
201
202
203
204
205
206
207
208
209
210
211

  describe "user registration" do
    @full_user_data %{
      bio: "A guy",
      name: "my name",
      nickname: "nick",
      password: "test",
      password_confirmation: "test",
      email: "email@example.com"
    }

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    test "it autofollows accounts that are set for it" do
      user = insert(:user)
      remote_user = insert(:user, %{local: false})

      Pleroma.Config.put([:instance, :autofollowed_nicknames], [
        user.nickname,
        remote_user.nickname
      ])

      cng = User.register_changeset(%User{}, @full_user_data)

      {:ok, registered_user} = User.register(cng)

      assert User.following?(registered_user, user)
      refute User.following?(registered_user, remote_user)
lain's avatar
lain committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

      Pleroma.Config.put([:instance, :autofollowed_nicknames], [])
    end

    test "it sends a welcome message if it is set" do
      welcome_user = insert(:user)

      Pleroma.Config.put([:instance, :welcome_user_nickname], welcome_user.nickname)
      Pleroma.Config.put([:instance, :welcome_message], "Hello, this is a cool site")

      cng = User.register_changeset(%User{}, @full_user_data)
      {:ok, registered_user} = User.register(cng)

      activity = Repo.one(Pleroma.Activity)
      assert registered_user.ap_id in activity.recipients
      assert activity.data["object"]["content"] =~ "cool site"
243
      assert activity.actor == welcome_user.ap_id
lain's avatar
lain committed
244
245
246

      Pleroma.Config.put([:instance, :welcome_user_nickname], nil)
      Pleroma.Config.put([:instance, :welcome_message], nil)
247
248
    end

vaartis's avatar
vaartis committed
249
    test "it requires an email, name, nickname and password, bio is optional" do
lain's avatar
lain committed
250
      @full_user_data
lain's avatar
lain committed
251
252
      |> Map.keys()
      |> Enum.each(fn key ->
lain's avatar
lain committed
253
254
        params = Map.delete(@full_user_data, key)
        changeset = User.register_changeset(%User{}, params)
vaartis's avatar
vaartis committed
255

lain's avatar
lain committed
256
        assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
lain's avatar
lain committed
257
258
259
      end)
    end

lain's avatar
lain committed
260
261
262
263
264
265
266
267
268
269
270
271
272
273
    test "it restricts certain nicknames" do
      [restricted_name | _] = Pleroma.Config.get([Pleroma.User, :restricted_nicknames])

      assert is_bitstring(restricted_name)

      params =
        @full_user_data
        |> Map.put(:nickname, restricted_name)

      changeset = User.register_changeset(%User{}, params)

      refute changeset.valid?
    end

lain's avatar
lain committed
274
275
276
277
278
279
280
    test "it sets the password_hash, ap_id and following fields" do
      changeset = User.register_changeset(%User{}, @full_user_data)

      assert changeset.valid?

      assert is_binary(changeset.changes[:password_hash])
      assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
lain's avatar
lain committed
281
282
283
284
285

      assert changeset.changes[:following] == [
               User.ap_followers(%User{nickname: @full_user_data.nickname})
             ]

286
      assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
lain's avatar
lain committed
287
    end
288
289
290
291
292
293
294
295
296
297
298
299

    test "it ensures info is not nil" do
      changeset = User.register_changeset(%User{}, @full_user_data)

      assert changeset.valid?

      {:ok, user} =
        changeset
        |> Repo.insert()

      refute is_nil(user.info)
    end
lain's avatar
lain committed
300
  end
lain's avatar
lain committed
301

302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  describe "user registration, with :account_activation_required" do
    @full_user_data %{
      bio: "A guy",
      name: "my name",
      nickname: "nick",
      password: "test",
      password_confirmation: "test",
      email: "email@example.com"
    }

    setup do
      setting = Pleroma.Config.get([:instance, :account_activation_required])

      unless setting do
        Pleroma.Config.put([:instance, :account_activation_required], true)
        on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
      end

      :ok
    end

    test "it creates unconfirmed user" do
      changeset = User.register_changeset(%User{}, @full_user_data)
      assert changeset.valid?

      {:ok, user} = Repo.insert(changeset)

      assert user.info.confirmation_pending
      assert user.info.confirmation_token
    end

    test "it creates confirmed user if :confirmed option is given" do
      changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
      assert changeset.valid?

      {:ok, user} = Repo.insert(changeset)

      refute user.info.confirmation_pending
      refute user.info.confirmation_token
    end
  end

Maksim's avatar
Maksim committed
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  describe "get_or_fetch/1" do
    test "gets an existing user by nickname" do
      user = insert(:user)
      fetched_user = User.get_or_fetch(user.nickname)

      assert user == fetched_user
    end

    test "gets an existing user by ap_id" do
      ap_id = "http://mastodon.example.org/users/admin"

      user =
        insert(
          :user,
          local: false,
          nickname: "admin@mastodon.example.org",
          ap_id: ap_id,
          info: %{}
        )

      fetched_user = User.get_or_fetch(ap_id)
      freshed_user = refresh_record(user)
      assert freshed_user == fetched_user
    end
  end

lain's avatar
lain committed
370
371
372
373
374
375
376
377
  describe "fetching a user from nickname or trying to build one" do
    test "gets an existing user" do
      user = insert(:user)
      fetched_user = User.get_or_fetch_by_nickname(user.nickname)

      assert user == fetched_user
    end

378
379
380
381
382
383
384
    test "gets an existing user, case insensitive" do
      user = insert(:user, nickname: "nick")
      fetched_user = User.get_or_fetch_by_nickname("NICK")

      assert user == fetched_user
    end

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
    test "gets an existing user by fully qualified nickname" do
      user = insert(:user)

      fetched_user =
        User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())

      assert user == fetched_user
    end

    test "gets an existing user by fully qualified nickname, case insensitive" do
      user = insert(:user, nickname: "nick")
      casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())

      fetched_user = User.get_or_fetch_by_nickname(casing_altered_fqn)

      assert user == fetched_user
    end

lain's avatar
lain committed
403
404
405
406
407
408
409
410
411
    test "fetches an external user via ostatus if no user exists" do
      fetched_user = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
      assert fetched_user.nickname == "shp@social.heldscal.la"
    end

    test "returns nil if no user could be fetched" do
      fetched_user = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
      assert fetched_user == nil
    end
lain's avatar
lain committed
412
413
414
415
416

    test "returns nil for nonexistant local user" do
      fetched_user = User.get_or_fetch_by_nickname("nonexistant")
      assert fetched_user == nil
    end
417
418
419
420
421
422
423
424
425
426

    test "updates an existing user, if stale" do
      a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)

      orig_user =
        insert(
          :user,
          local: false,
          nickname: "admin@mastodon.example.org",
          ap_id: "http://mastodon.example.org/users/admin",
lain's avatar
lain committed
427
428
          last_refreshed_at: a_week_ago,
          info: %{}
429
430
431
432
433
        )

      assert orig_user.last_refreshed_at == a_week_ago

      user = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
lain's avatar
lain committed
434
      assert user.info.source_data["endpoints"]
435
436
437

      refute user.last_refreshed_at == orig_user.last_refreshed_at
    end
lain's avatar
lain committed
438
  end
439
440
441

  test "returns an ap_id for a user" do
    user = insert(:user)
lain's avatar
lain committed
442
443
444
445
446
447
448

    assert User.ap_id(user) ==
             Pleroma.Web.Router.Helpers.o_status_url(
               Pleroma.Web.Endpoint,
               :feed_redirect,
               user.nickname
             )
449
450
451
452
  end

  test "returns an ap_followers link for a user" do
    user = insert(:user)
lain's avatar
lain committed
453
454
455
456
457
458
459

    assert User.ap_followers(user) ==
             Pleroma.Web.Router.Helpers.o_status_url(
               Pleroma.Web.Endpoint,
               :feed_redirect,
               user.nickname
             ) <> "/followers"
460
  end
lain's avatar
lain committed
461
462
463
464
465
466
467

  describe "remote user creation changeset" do
    @valid_remote %{
      bio: "hello",
      name: "Someone",
      nickname: "a@b.de",
      ap_id: "http...",
lain's avatar
lain committed
468
469
      info: %{some: "info"},
      avatar: %{some: "avatar"}
lain's avatar
lain committed
470
471
472
473
474
475
476
    }

    test "it confirms validity" do
      cs = User.remote_user_creation(@valid_remote)
      assert cs.valid?
    end

477
478
479
    test "it sets the follower_adress" do
      cs = User.remote_user_creation(@valid_remote)
      # remote users get a fake local follower address
lain's avatar
lain committed
480
481
      assert cs.changes.follower_address ==
               User.ap_followers(%User{nickname: @valid_remote[:nickname]})
482
483
    end

lain's avatar
lain committed
484
485
    test "it enforces the fqn format for nicknames" do
      cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
lain's avatar
lain committed
486
487
      assert cs.changes.local == false
      assert cs.changes.avatar
lain's avatar
lain committed
488
489
490
491
      refute cs.valid?
    end

    test "it has required fields" do
492
      [:name, :ap_id]
lain's avatar
lain committed
493
      |> Enum.each(fn field ->
lain's avatar
lain committed
494
495
496
497
498
499
        cs = User.remote_user_creation(Map.delete(@valid_remote, field))
        refute cs.valid?
      end)
    end

    test "it restricts some sizes" do
lain's avatar
lain committed
500
      [bio: 5000, name: 100]
lain's avatar
lain committed
501
      |> Enum.each(fn {field, size} ->
lain's avatar
lain committed
502
503
504
505
506
507
508
509
510
511
        string = String.pad_leading(".", size)
        cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
        assert cs.valid?

        string = String.pad_leading(".", size + 1)
        cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
        refute cs.valid?
      end)
    end
  end
lain's avatar
lain committed
512
513
514
515
516
517
518
519
520
521
522
523
524

  describe "followers and friends" do
    test "gets all followers for a given user" do
      user = insert(:user)
      follower_one = insert(:user)
      follower_two = insert(:user)
      not_follower = insert(:user)

      {:ok, follower_one} = User.follow(follower_one, user)
      {:ok, follower_two} = User.follow(follower_two, user)

      {:ok, res} = User.get_followers(user)

lain's avatar
lain committed
525
526
527
      assert Enum.member?(res, follower_one)
      assert Enum.member?(res, follower_two)
      refute Enum.member?(res, not_follower)
lain's avatar
lain committed
528
529
530
531
532
533
534
535
536
537
538
539
540
    end

    test "gets all friends (followed users) for a given user" do
      user = insert(:user)
      followed_one = insert(:user)
      followed_two = insert(:user)
      not_followed = insert(:user)

      {:ok, user} = User.follow(user, followed_one)
      {:ok, user} = User.follow(user, followed_two)

      {:ok, res} = User.get_friends(user)

541
542
      followed_one = User.get_by_ap_id(followed_one.ap_id)
      followed_two = User.get_by_ap_id(followed_two.ap_id)
lain's avatar
lain committed
543
544
545
      assert Enum.member?(res, followed_one)
      assert Enum.member?(res, followed_two)
      refute Enum.member?(res, not_followed)
lain's avatar
lain committed
546
547
    end
  end
548
549
550
551
552
553
554

  describe "updating note and follower count" do
    test "it sets the info->note_count property" do
      note = insert(:note)

      user = User.get_by_ap_id(note.data["actor"])

lain's avatar
lain committed
555
      assert user.info.note_count == 0
556
557
558

      {:ok, user} = User.update_note_count(user)

lain's avatar
lain committed
559
      assert user.info.note_count == 1
560
561
    end

562
563
564
565
    test "it increases the info->note_count property" do
      note = insert(:note)
      user = User.get_by_ap_id(note.data["actor"])

lain's avatar
lain committed
566
      assert user.info.note_count == 0
567
568
569

      {:ok, user} = User.increase_note_count(user)

lain's avatar
lain committed
570
      assert user.info.note_count == 1
571
572
573

      {:ok, user} = User.increase_note_count(user)

lain's avatar
lain committed
574
      assert user.info.note_count == 2
575
576
    end

577
578
579
580
    test "it decreases the info->note_count property" do
      note = insert(:note)
      user = User.get_by_ap_id(note.data["actor"])

lain's avatar
lain committed
581
      assert user.info.note_count == 0
582
583
584

      {:ok, user} = User.increase_note_count(user)

lain's avatar
lain committed
585
      assert user.info.note_count == 1
586
587
588

      {:ok, user} = User.decrease_note_count(user)

lain's avatar
lain committed
589
      assert user.info.note_count == 0
590
591
592

      {:ok, user} = User.decrease_note_count(user)

lain's avatar
lain committed
593
      assert user.info.note_count == 0
594
595
    end

596
597
598
599
600
601
    test "it sets the info->follower_count property" do
      user = insert(:user)
      follower = insert(:user)

      User.follow(follower, user)

lain's avatar
lain committed
602
      assert user.info.follower_count == 0
603
604
605

      {:ok, user} = User.update_follower_count(user)

lain's avatar
lain committed
606
      assert user.info.follower_count == 1
607
608
    end
  end
lain's avatar
lain committed
609

610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  describe "follow_import" do
    test "it imports user followings from list" do
      [user1, user2, user3] = insert_list(3, :user)

      identifiers = [
        user2.ap_id,
        user3.nickname
      ]

      result = User.follow_import(user1, identifiers)
      assert is_list(result)
      assert result == [user2, user3]
    end
  end

lain's avatar
lain committed
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
  describe "mutes" do
    test "it mutes people" do
      user = insert(:user)
      muted_user = insert(:user)

      refute User.mutes?(user, muted_user)

      {:ok, user} = User.mute(user, muted_user)

      assert User.mutes?(user, muted_user)
    end

    test "it unmutes users" do
      user = insert(:user)
      muted_user = insert(:user)

      {:ok, user} = User.mute(user, muted_user)
      {:ok, user} = User.unmute(user, muted_user)

      refute User.mutes?(user, muted_user)
    end
  end

lain's avatar
lain committed
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
  describe "blocks" do
    test "it blocks people" do
      user = insert(:user)
      blocked_user = insert(:user)

      refute User.blocks?(user, blocked_user)

      {:ok, user} = User.block(user, blocked_user)

      assert User.blocks?(user, blocked_user)
    end

    test "it unblocks users" do
      user = insert(:user)
      blocked_user = insert(:user)

      {:ok, user} = User.block(user, blocked_user)
      {:ok, user} = User.unblock(user, blocked_user)

      refute User.blocks?(user, blocked_user)
    end
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

    test "blocks tear down cyclical follow relationships" do
      blocker = insert(:user)
      blocked = insert(:user)

      {:ok, blocker} = User.follow(blocker, blocked)
      {:ok, blocked} = User.follow(blocked, blocker)

      assert User.following?(blocker, blocked)
      assert User.following?(blocked, blocker)

      {:ok, blocker} = User.block(blocker, blocked)
      blocked = Repo.get(User, blocked.id)

      assert User.blocks?(blocker, blocked)

      refute User.following?(blocker, blocked)
      refute User.following?(blocked, blocker)
    end

    test "blocks tear down blocker->blocked follow relationships" do
      blocker = insert(:user)
      blocked = insert(:user)

      {:ok, blocker} = User.follow(blocker, blocked)

      assert User.following?(blocker, blocked)
      refute User.following?(blocked, blocker)

      {:ok, blocker} = User.block(blocker, blocked)
      blocked = Repo.get(User, blocked.id)

      assert User.blocks?(blocker, blocked)

      refute User.following?(blocker, blocked)
      refute User.following?(blocked, blocker)
    end

    test "blocks tear down blocked->blocker follow relationships" do
      blocker = insert(:user)
      blocked = insert(:user)

      {:ok, blocked} = User.follow(blocked, blocker)

      refute User.following?(blocker, blocked)
      assert User.following?(blocked, blocker)

      {:ok, blocker} = User.block(blocker, blocked)
      blocked = Repo.get(User, blocked.id)

      assert User.blocks?(blocker, blocked)

      refute User.following?(blocker, blocked)
      refute User.following?(blocked, blocker)
    end
lain's avatar
lain committed
724
  end
725

eal's avatar
eal committed
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  describe "domain blocking" do
    test "blocks domains" do
      user = insert(:user)
      collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})

      {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")

      assert User.blocks?(user, collateral_user)
    end

    test "unblocks domains" do
      user = insert(:user)
      collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})

      {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
      {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")

      refute User.blocks?(user, collateral_user)
    end
  end

747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
  describe "blocks_import" do
    test "it imports user blocks from list" do
      [user1, user2, user3] = insert_list(3, :user)

      identifiers = [
        user2.ap_id,
        user3.nickname
      ]

      result = User.blocks_import(user1, identifiers)
      assert is_list(result)
      assert result == [user2, user3]
    end
  end

762
763
764
765
766
767
  test "get recipients from activity" do
    actor = insert(:user)
    user = insert(:user, local: true)
    user_two = insert(:user, local: false)
    addressed = insert(:user, local: true)
    addressed_remote = insert(:user, local: false)
lain's avatar
lain committed
768
769
770
771
772

    {:ok, activity} =
      CommonAPI.post(actor, %{
        "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
      })
773

Maxim Filippov's avatar
Maxim Filippov committed
774
775
    assert Enum.map([actor, addressed], & &1.ap_id) --
             Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
776
777

    {:ok, user} = User.follow(user, actor)
lain's avatar
lain committed
778
    {:ok, _user_two} = User.follow(user_two, actor)
779
    recipients = User.get_recipients_from_activity(activity)
Maxim Filippov's avatar
Maxim Filippov committed
780
    assert length(recipients) == 3
781
782
783
    assert user in recipients
    assert addressed in recipients
  end
lain's avatar
lain committed
784

scarlett's avatar
scarlett committed
785
  test ".deactivate can de-activate then re-activate a user" do
lain's avatar
lain committed
786
    user = insert(:user)
lain's avatar
lain committed
787
    assert false == user.info.deactivated
lain's avatar
lain committed
788
    {:ok, user} = User.deactivate(user)
lain's avatar
lain committed
789
    assert true == user.info.deactivated
scarlett's avatar
scarlett committed
790
    {:ok, user} = User.deactivate(user, false)
lain's avatar
lain committed
791
    assert false == user.info.deactivated
lain's avatar
lain committed
792
  end
lain's avatar
lain committed
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808

  test ".delete deactivates a user, all follow relationships and all create activities" do
    user = insert(:user)
    followed = insert(:user)
    follower = insert(:user)

    {:ok, user} = User.follow(user, followed)
    {:ok, follower} = User.follow(follower, user)

    {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
    {:ok, activity_two} = CommonAPI.post(follower, %{"status" => "3hu"})

    {:ok, _, _} = CommonAPI.favorite(activity_two.id, user)
    {:ok, _, _} = CommonAPI.favorite(activity.id, follower)
    {:ok, _, _} = CommonAPI.repeat(activity.id, follower)

809
    {:ok, _} = User.delete(user)
lain's avatar
lain committed
810
811
812
813
814

    followed = Repo.get(User, followed.id)
    follower = Repo.get(User, follower.id)
    user = Repo.get(User, user.id)

lain's avatar
lain committed
815
    assert user.info.deactivated
lain's avatar
lain committed
816
817
818
819

    refute User.following?(user, followed)
    refute User.following?(followed, follower)

lain's avatar
lain committed
820
821
822
    # TODO: Remove favorites, repeats, delete activities.

    refute Repo.get(Activity, activity.id)
lain's avatar
lain committed
823
  end
824
825
826
827

  test "get_public_key_for_ap_id fetches a user that's not in the db" do
    assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
  end
lain's avatar
lain committed
828
829
830

  test "insert or update a user from given data" do
    user = insert(:user, %{nickname: "nick@name.de"})
lain's avatar
lain committed
831
    data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
lain's avatar
lain committed
832
833
834

    assert {:ok, %User{}} = User.insert_or_update_user(data)
  end
835
836

  describe "per-user rich-text filtering" do
Rin Toshaka's avatar
Rin Toshaka committed
837
    test "html_filter_policy returns default policies, when rich-text is enabled" do
838
839
      user = insert(:user)

840
      assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
841
842
843
    end

    test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
lain's avatar
lain committed
844
      user = insert(:user, %{info: %{no_rich_text: true}})
845
846
847
848

      assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
    end
  end
849
850
851
852

  describe "caching" do
    test "invalidate_cache works" do
      user = insert(:user)
Maksim's avatar
Maksim committed
853
      _user_info = User.get_cached_user_info(user)
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875

      User.invalidate_cache(user)

      {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
      {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
      {:ok, nil} = Cachex.get(:user_cache, "user_info:#{user.id}")
    end

    test "User.delete() plugs any possible zombie objects" do
      user = insert(:user)

      {:ok, _} = User.delete(user)

      {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")

      assert cached_user != user

      {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")

      assert cached_user != user
    end
  end
876
877

  describe "User.search" do
878
879
    test "finds a user by full or partial nickname" do
      user = insert(:user, %{nickname: "john"})
880

881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
      Enum.each(["john", "jo", "j"], fn query ->
        assert user == User.search(query) |> List.first() |> Map.put(:search_rank, nil)
      end)
    end

    test "finds a user by full or partial name" do
      user = insert(:user, %{name: "John Doe"})

      Enum.each(["John Doe", "JOHN", "doe", "j d", "j", "d"], fn query ->
        assert user == User.search(query) |> List.first() |> Map.put(:search_rank, nil)
      end)
    end

    test "finds users, preferring nickname matches over name matches" do
      u1 = insert(:user, %{name: "lain", nickname: "nick1"})
      u2 = insert(:user, %{nickname: "lain", name: "nick1"})

      assert [u2.id, u1.id] == Enum.map(User.search("lain"), & &1.id)
    end

    test "finds users, considering density of matched tokens" do
      u1 = insert(:user, %{name: "Bar Bar plus Word Word"})
      u2 = insert(:user, %{name: "Word Word Bar Bar Bar"})

      assert [u2.id, u1.id] == Enum.map(User.search("bar word"), & &1.id)
    end

    test "finds users, ranking by similarity" do
      u1 = insert(:user, %{name: "lain"})
      _u2 = insert(:user, %{name: "ean"})
      u3 = insert(:user, %{name: "ebn", nickname: "lain@mastodon.social"})
      u4 = insert(:user, %{nickname: "lain@pleroma.soykaf.com"})

      assert [u4.id, u3.id, u1.id] == Enum.map(User.search("lain@ple"), & &1.id)
    end

917
918
919
920
921
922
    test "finds users, handling misspelled requests" do
      u1 = insert(:user, %{name: "lain"})

      assert [u1.id] == Enum.map(User.search("laiin"), & &1.id)
    end

923
924
925
926
927
928
929
930
931
932
    test "finds users, boosting ranks of friends and followers" do
      u1 = insert(:user)
      u2 = insert(:user, %{name: "Doe"})
      follower = insert(:user, %{name: "Doe"})
      friend = insert(:user, %{name: "Doe"})

      {:ok, follower} = User.follow(follower, u1)
      {:ok, u1} = User.follow(u1, friend)

      assert [friend.id, follower.id, u2.id] == Enum.map(User.search("doe", false, u1), & &1.id)
933
    end
cascode's avatar
cascode committed
934
935
936
937
938
939

    test "finds a user whose name is nil" do
      _user = insert(:user, %{name: "notamatch", nickname: "testuser@pleroma.amplifie.red"})
      user_two = insert(:user, %{name: nil, nickname: "lain@pleroma.soykaf.com"})

      assert user_two ==
cascode's avatar
cascode committed
940
941
               User.search("lain@pleroma.soykaf.com")
               |> List.first()
942
               |> Map.put(:search_rank, nil)
cascode's avatar
cascode committed
943
    end
944
945
946
947
948
949
950

    test "does not yield false-positive matches" do
      insert(:user, %{name: "John Doe"})

      Enum.each(["mary", "a", ""], fn query ->
        assert [] == User.search(query)
      end)
cascode's avatar
cascode committed
951
    end
952
953
954
955
956
957
958
959
960
961

    test "works with URIs" do
      results = User.search("http://mastodon.example.org/users/admin", true)
      result = results |> List.first()

      user = User.get_by_ap_id("http://mastodon.example.org/users/admin")

      assert length(results) == 1
      assert user == result |> Map.put(:search_rank, nil)
    end
962
  end
963

964
  test "auth_active?/1 works correctly" do
965
966
967
968
969
970
    Pleroma.Config.put([:instance, :account_activation_required], true)

    local_user = insert(:user, local: true, info: %{confirmation_pending: true})
    confirmed_user = insert(:user, local: true, info: %{confirmation_pending: false})
    remote_user = insert(:user, local: false)

971
972
973
    refute User.auth_active?(local_user)
    assert User.auth_active?(confirmed_user)
    assert User.auth_active?(remote_user)
974
975
976

    Pleroma.Config.put([:instance, :account_activation_required], false)
  end
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004

  describe "superuser?/1" do
    test "returns false for unprivileged users" do
      user = insert(:user, local: true)

      refute User.superuser?(user)
    end

    test "returns false for remote users" do
      user = insert(:user, local: false)
      remote_admin_user = insert(:user, local: false, info: %{is_admin: true})

      refute User.superuser?(user)
      refute User.superuser?(remote_admin_user)
    end

    test "returns true for local moderators" do
      user = insert(:user, local: true, info: %{is_moderator: true})

      assert User.superuser?(user)
    end

    test "returns true for local admins" do
      user = insert(:user, local: true, info: %{is_admin: true})

      assert User.superuser?(user)
    end
  end
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041

  describe "visible_for?/2" do
    test "returns true when the account is itself" do
      user = insert(:user, local: true)

      assert User.visible_for?(user, user)
    end

    test "returns false when the account is unauthenticated and auth is required" do
      Pleroma.Config.put([:instance, :account_activation_required], true)

      user = insert(:user, local: true, info: %{confirmation_pending: true})
      other_user = insert(:user, local: true)

      refute User.visible_for?(user, other_user)

      Pleroma.Config.put([:instance, :account_activation_required], false)
    end

    test "returns true when the account is unauthenticated and auth is not required" do
      user = insert(:user, local: true, info: %{confirmation_pending: true})
      other_user = insert(:user, local: true)

      assert User.visible_for?(user, other_user)
    end

    test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
      Pleroma.Config.put([:instance, :account_activation_required], true)

      user = insert(:user, local: true, info: %{confirmation_pending: true})
      other_user = insert(:user, local: true, info: %{is_admin: true})

      assert User.visible_for?(user, other_user)

      Pleroma.Config.put([:instance, :account_activation_required], false)
    end
  end
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056

  describe "parse_bio/2" do
    test "preserves hosts in user links text" do
      remote_user = insert(:user, local: false, nickname: "nick@domain.com")
      user = insert(:user)
      bio = "A.k.a. @nick@domain.com"

      expected_text =
        "A.k.a. <span class='h-card'><a data-user='#{remote_user.id}' class='u-url mention' href='#{
          remote_user.ap_id
        }'>" <> "@<span>nick@domain.com</span></a></span>"

      assert expected_text == User.parse_bio(bio, user)
    end
  end
Haelwenn's avatar
Haelwenn committed
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083

  test "bookmarks" do
    user = insert(:user)

    {:ok, activity1} =
      CommonAPI.post(user, %{
        "status" => "heweoo!"
      })

    id1 = activity1.data["object"]["id"]

    {:ok, activity2} =
      CommonAPI.post(user, %{
        "status" => "heweoo!"
      })

    id2 = activity2.data["object"]["id"]

    assert {:ok, user_state1} = User.bookmark(user, id1)
    assert user_state1.bookmarks == [id1]

    assert {:ok, user_state2} = User.unbookmark(user, id1)
    assert user_state2.bookmarks == []

    assert {:ok, user_state3} = User.bookmark(user, id2)
    assert user_state3.bookmarks == [id2]
  end
lain's avatar
lain committed
1084
end