user_test.exs 34 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
defmodule Pleroma.UserTest do
Haelwenn's avatar
Haelwenn committed
6
  alias Pleroma.Activity
7
  alias Pleroma.Builders.UserBuilder
8
  alias Pleroma.Object
Haelwenn's avatar
Haelwenn committed
9
10
  alias Pleroma.Repo
  alias Pleroma.User
11
  alias Pleroma.Web.CommonAPI
12

lain's avatar
lain committed
13
14
  use Pleroma.DataCase

lain's avatar
lain committed
15
16
  import Pleroma.Factory

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

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  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
39
  test "ap_id returns the activity pub id for the user" do
lain's avatar
lain committed
40
    user = UserBuilder.build()
lain's avatar
lain committed
41

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

    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
48
    user = UserBuilder.build()
lain's avatar
lain committed
49
50
51
52
53

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

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

lain's avatar
lain committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  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

69
70
71
72
73
74
75
76
77
78
79
80
81
82
  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
83
84
  test "follow_all follows mutliple users" do
    user = insert(:user)
lain's avatar
lain committed
85
    followed_zero = insert(:user)
lain's avatar
lain committed
86
87
    followed_one = insert(:user)
    followed_two = insert(:user)
lain's avatar
lain committed
88
    blocked = insert(:user)
lain's avatar
lain committed
89
    not_followed = insert(:user)
90
    reverse_blocked = insert(:user)
lain's avatar
lain committed
91

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

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

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

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

107
108
109
110
111
112
113
114
115
116
117
118
119
  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
120
  test "follow takes a user and another user" do
lain's avatar
lain committed
121
122
    user = insert(:user)
    followed = insert(:user)
lain's avatar
lain committed
123

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

minibikini's avatar
minibikini committed
126
    user = User.get_cached_by_id(user.id)
lain's avatar
lain committed
127

minibikini's avatar
minibikini committed
128
    followed = User.get_cached_by_ap_id(followed.ap_id)
lain's avatar
lain committed
129
    assert followed.info.follower_count == 1
130

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

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

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

141
142
143
144
145
146
147
148
149
  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

150
151
152
153
154
155
156
157
158
  test "can't subscribe to a user who blocked us" do
    blocker = insert(:user)
    blocked = insert(:user)

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

    {:error, _} = User.subscribe(blocked, blocker)
  end

kaniini's avatar
kaniini committed
159
  test "local users do not automatically follow local locked accounts" do
lain's avatar
lain committed
160
161
    follower = insert(:user, info: %{locked: true})
    followed = insert(:user, info: %{locked: true})
kaniini's avatar
kaniini committed
162
163
164
165
166
167

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

    refute User.following?(follower, followed)
  end

lain's avatar
lain committed
168
169
170
171
  # 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
172

lain's avatar
lain committed
173
  #   assert followed.local == false
lain's avatar
lain committed
174

lain's avatar
lain committed
175
176
  #   {:ok, user} = User.follow(user, followed)
  #   assert User.ap_followers(followed) in user.following
lain's avatar
lain committed
177

lain's avatar
lain committed
178
179
180
  #   query = from w in WebsubClientSubscription,
  #   where: w.topic == ^followed.info["topic"]
  #   websub = Repo.one(query)
lain's avatar
lain committed
181

lain's avatar
lain committed
182
183
  #   assert websub
  # end
lain's avatar
lain committed
184

lain's avatar
lain committed
185
  test "unfollow takes a user and another user" do
lain's avatar
lain committed
186
187
    followed = insert(:user)
    user = insert(:user, %{following: [User.ap_followers(followed)]})
lain's avatar
lain committed
188

lain's avatar
lain committed
189
    {:ok, user, _activity} = User.unfollow(user, followed)
lain's avatar
lain committed
190

minibikini's avatar
minibikini committed
191
    user = User.get_cached_by_id(user.id)
lain's avatar
lain committed
192
193
194

    assert user.following == []
  end
195

196
197
198
199
200
  test "unfollow doesn't unfollow yourself" do
    user = insert(:user)

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

minibikini's avatar
minibikini committed
201
    user = User.get_cached_by_id(user.id)
202
203
204
    assert user.following == [user.ap_id]
  end

205
  test "test if a user is following another user" do
lain's avatar
lain committed
206
207
    followed = insert(:user)
    user = insert(:user, %{following: [User.ap_followers(followed)]})
208
209
210
211

    assert User.following?(user, followed)
    refute User.following?(followed, user)
  end
lain's avatar
lain committed
212

213
214
215
216
217
218
219
  test "fetches correct profile for nickname beginning with number" do
    # Use old-style integer ID to try to reproduce the problem
    user = insert(:user, %{id: 1080})
    userwithnumbers = insert(:user, %{nickname: "#{user.id}garbage"})
    assert userwithnumbers == User.get_cached_by_nickname_or_id(userwithnumbers.nickname)
  end

lain's avatar
lain committed
220
221
222
223
224
225
226
227
228
229
  describe "user registration" do
    @full_user_data %{
      bio: "A guy",
      name: "my name",
      nickname: "nick",
      password: "test",
      password_confirmation: "test",
      email: "email@example.com"
    }

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
    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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259

      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
260
      assert Object.normalize(activity).data["content"] =~ "cool site"
261
      assert activity.actor == welcome_user.ap_id
lain's avatar
lain committed
262
263
264

      Pleroma.Config.put([:instance, :welcome_user_nickname], nil)
      Pleroma.Config.put([:instance, :welcome_message], nil)
265
266
    end

vaartis's avatar
vaartis committed
267
    test "it requires an email, name, nickname and password, bio is optional" do
lain's avatar
lain committed
268
      @full_user_data
lain's avatar
lain committed
269
270
      |> Map.keys()
      |> Enum.each(fn key ->
lain's avatar
lain committed
271
272
        params = Map.delete(@full_user_data, key)
        changeset = User.register_changeset(%User{}, params)
vaartis's avatar
vaartis committed
273

lain's avatar
lain committed
274
        assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
lain's avatar
lain committed
275
276
277
      end)
    end

lain's avatar
lain committed
278
279
280
281
282
283
284
285
286
287
288
289
290
291
    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
292
293
294
295
296
297
298
    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
299
300
301
302
303

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

304
      assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
lain's avatar
lain committed
305
    end
306
307
308
309
310
311
312
313
314
315
316
317

    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
318
  end
lain's avatar
lain committed
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
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  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
362
363
364
  describe "get_or_fetch/1" do
    test "gets an existing user by nickname" do
      user = insert(:user)
Alexander Strizhakov's avatar
Alexander Strizhakov committed
365
      {:ok, fetched_user} = User.get_or_fetch(user.nickname)
Maksim's avatar
Maksim committed
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

      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: %{}
        )

Alexander Strizhakov's avatar
Alexander Strizhakov committed
382
      {:ok, fetched_user} = User.get_or_fetch(ap_id)
Maksim's avatar
Maksim committed
383
384
385
386
387
      freshed_user = refresh_record(user)
      assert freshed_user == fetched_user
    end
  end

lain's avatar
lain committed
388
389
390
  describe "fetching a user from nickname or trying to build one" do
    test "gets an existing user" do
      user = insert(:user)
Alexander Strizhakov's avatar
Alexander Strizhakov committed
391
      {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
lain's avatar
lain committed
392
393
394
395

      assert user == fetched_user
    end

396
397
    test "gets an existing user, case insensitive" do
      user = insert(:user, nickname: "nick")
Alexander Strizhakov's avatar
Alexander Strizhakov committed
398
      {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
399
400
401
402

      assert user == fetched_user
    end

403
404
405
    test "gets an existing user by fully qualified nickname" do
      user = insert(:user)

Alexander Strizhakov's avatar
Alexander Strizhakov committed
406
      {:ok, fetched_user} =
407
408
409
410
411
412
413
414
415
        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())

Alexander Strizhakov's avatar
Alexander Strizhakov committed
416
      {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
417
418
419
420

      assert user == fetched_user
    end

lain's avatar
lain committed
421
    test "fetches an external user via ostatus if no user exists" do
Alexander Strizhakov's avatar
Alexander Strizhakov committed
422
      {:ok, fetched_user} = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
lain's avatar
lain committed
423
424
425
426
      assert fetched_user.nickname == "shp@social.heldscal.la"
    end

    test "returns nil if no user could be fetched" do
Alexander Strizhakov's avatar
Alexander Strizhakov committed
427
428
      {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
      assert fetched_user == "not found nonexistant@social.heldscal.la"
lain's avatar
lain committed
429
    end
lain's avatar
lain committed
430
431

    test "returns nil for nonexistant local user" do
Alexander Strizhakov's avatar
Alexander Strizhakov committed
432
433
      {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
      assert fetched_user == "not found nonexistant"
lain's avatar
lain committed
434
    end
435
436
437
438
439
440
441
442
443
444

    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
445
446
          last_refreshed_at: a_week_ago,
          info: %{}
447
448
449
450
        )

      assert orig_user.last_refreshed_at == a_week_ago

Alexander Strizhakov's avatar
Alexander Strizhakov committed
451
      {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
lain's avatar
lain committed
452
      assert user.info.source_data["endpoints"]
453
454
455

      refute user.last_refreshed_at == orig_user.last_refreshed_at
    end
lain's avatar
lain committed
456
  end
457
458
459

  test "returns an ap_id for a user" do
    user = insert(:user)
lain's avatar
lain committed
460
461
462
463
464
465
466

    assert User.ap_id(user) ==
             Pleroma.Web.Router.Helpers.o_status_url(
               Pleroma.Web.Endpoint,
               :feed_redirect,
               user.nickname
             )
467
468
469
470
  end

  test "returns an ap_followers link for a user" do
    user = insert(:user)
lain's avatar
lain committed
471
472
473
474
475
476
477

    assert User.ap_followers(user) ==
             Pleroma.Web.Router.Helpers.o_status_url(
               Pleroma.Web.Endpoint,
               :feed_redirect,
               user.nickname
             ) <> "/followers"
478
  end
lain's avatar
lain committed
479
480
481
482
483
484
485

  describe "remote user creation changeset" do
    @valid_remote %{
      bio: "hello",
      name: "Someone",
      nickname: "a@b.de",
      ap_id: "http...",
lain's avatar
lain committed
486
487
      info: %{some: "info"},
      avatar: %{some: "avatar"}
lain's avatar
lain committed
488
489
490
491
492
493
494
    }

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

495
496
497
    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
498
499
      assert cs.changes.follower_address ==
               User.ap_followers(%User{nickname: @valid_remote[:nickname]})
500
501
    end

lain's avatar
lain committed
502
503
    test "it enforces the fqn format for nicknames" do
      cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
lain's avatar
lain committed
504
505
      assert cs.changes.local == false
      assert cs.changes.avatar
lain's avatar
lain committed
506
507
508
509
      refute cs.valid?
    end

    test "it has required fields" do
510
      [:name, :ap_id]
lain's avatar
lain committed
511
      |> Enum.each(fn field ->
lain's avatar
lain committed
512
513
514
515
516
517
        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
518
      [bio: 5000, name: 100]
lain's avatar
lain committed
519
      |> Enum.each(fn {field, size} ->
lain's avatar
lain committed
520
521
522
523
524
525
526
527
528
529
        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
530
531
532
533
534
535
536
537
538
539
540
541
542

  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
543
544
545
      assert Enum.member?(res, follower_one)
      assert Enum.member?(res, follower_two)
      refute Enum.member?(res, not_follower)
lain's avatar
lain committed
546
547
548
549
550
551
552
553
554
555
556
557
558
    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)

minibikini's avatar
minibikini committed
559
560
      followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
      followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
lain's avatar
lain committed
561
562
563
      assert Enum.member?(res, followed_one)
      assert Enum.member?(res, followed_two)
      refute Enum.member?(res, not_followed)
lain's avatar
lain committed
564
565
    end
  end
566
567
568
569
570

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

minibikini's avatar
minibikini committed
571
      user = User.get_cached_by_ap_id(note.data["actor"])
572

lain's avatar
lain committed
573
      assert user.info.note_count == 0
574
575
576

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

lain's avatar
lain committed
577
      assert user.info.note_count == 1
578
579
    end

580
581
    test "it increases the info->note_count property" do
      note = insert(:note)
minibikini's avatar
minibikini committed
582
      user = User.get_cached_by_ap_id(note.data["actor"])
583

lain's avatar
lain committed
584
      assert user.info.note_count == 0
585
586
587

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

lain's avatar
lain committed
588
      assert user.info.note_count == 1
589
590
591

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

lain's avatar
lain committed
592
      assert user.info.note_count == 2
593
594
    end

595
596
    test "it decreases the info->note_count property" do
      note = insert(:note)
minibikini's avatar
minibikini committed
597
      user = User.get_cached_by_ap_id(note.data["actor"])
598

lain's avatar
lain committed
599
      assert user.info.note_count == 0
600
601
602

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

lain's avatar
lain committed
603
      assert user.info.note_count == 1
604
605
606

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

lain's avatar
lain committed
607
      assert user.info.note_count == 0
608
609
610

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

lain's avatar
lain committed
611
      assert user.info.note_count == 0
612
613
    end

614
615
616
617
618
619
    test "it sets the info->follower_count property" do
      user = insert(:user)
      follower = insert(:user)

      User.follow(follower, user)

lain's avatar
lain committed
620
      assert user.info.follower_count == 0
621
622
623

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

lain's avatar
lain committed
624
      assert user.info.follower_count == 1
625
626
    end
  end
lain's avatar
lain committed
627

628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
  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
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
  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
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
  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
687
688
689
690
691
692
693
694
695
696
697
698

    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)
minibikini's avatar
minibikini committed
699
      blocked = User.get_cached_by_id(blocked.id)
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716

      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)
minibikini's avatar
minibikini committed
717
      blocked = User.get_cached_by_id(blocked.id)
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734

      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)
minibikini's avatar
minibikini committed
735
      blocked = User.get_cached_by_id(blocked.id)
736
737
738
739
740
741

      assert User.blocks?(blocker, blocked)

      refute User.following?(blocker, blocked)
      refute User.following?(blocked, blocker)
    end
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

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

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

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

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

      assert User.blocks?(blocker, blocked)
      refute User.subscribed_to?(blocker, blocked)
      refute User.subscribed_to?(blocked, blocker)
    end
lain's avatar
lain committed
758
  end
759

eal's avatar
eal committed
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
  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

781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
  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

796
797
798
799
800
801
  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
802
803
804
805
806

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

Maxim Filippov's avatar
Maxim Filippov committed
808
809
    assert Enum.map([actor, addressed], & &1.ap_id) --
             Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
810
811

    {:ok, user} = User.follow(user, actor)
lain's avatar
lain committed
812
    {:ok, _user_two} = User.follow(user_two, actor)
813
    recipients = User.get_recipients_from_activity(activity)
Maxim Filippov's avatar
Maxim Filippov committed
814
    assert length(recipients) == 3
815
816
817
    assert user in recipients
    assert addressed in recipients
  end
lain's avatar
lain committed
818

scarlett's avatar
scarlett committed
819
  test ".deactivate can de-activate then re-activate a user" do
lain's avatar
lain committed
820
    user = insert(:user)
lain's avatar
lain committed
821
    assert false == user.info.deactivated
lain's avatar
lain committed
822
    {:ok, user} = User.deactivate(user)
lain's avatar
lain committed
823
    assert true == user.info.deactivated
scarlett's avatar
scarlett committed
824
    {:ok, user} = User.deactivate(user, false)
lain's avatar
lain committed
825
    assert false == user.info.deactivated
lain's avatar
lain committed
826
  end
lain's avatar
lain committed
827

828
829
830
831
832
833
834
835
836
837
  test ".delete_user_activities deletes all create activities" do
    user = insert(:user)

    {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
    {:ok, _} = User.delete_user_activities(user)

    # TODO: Remove favorites, repeats, delete activities.
    refute Activity.get_by_id(activity.id)
  end

lain's avatar
lain committed
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
  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)

853
    {:ok, _} = User.delete(user)
lain's avatar
lain committed
854

minibikini's avatar
minibikini committed
855
856
857
    followed = User.get_cached_by_id(followed.id)
    follower = User.get_cached_by_id(follower.id)
    user = User.get_cached_by_id(user.id)
lain's avatar
lain committed
858

lain's avatar
lain committed
859
    assert user.info.deactivated
lain's avatar
lain committed
860
861
862
863

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

lain's avatar
lain committed
864
865
    # TODO: Remove favorites, repeats, delete activities.

866
    refute Activity.get_by_id(activity.id)
lain's avatar
lain committed
867
  end
868
869
870
871

  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
872
873
874

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

    assert {:ok, %User{}} = User.insert_or_update_user(data)
  end
879
880

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

884
      assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
885
886
887
    end

    test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
lain's avatar
lain committed
888
      user = insert(:user, %{info: %{no_rich_text: true}})
889
890
891
892

      assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
    end
  end
893
894
895
896

  describe "caching" do
    test "invalidate_cache works" do
      user = insert(:user)
Maksim's avatar
Maksim committed
897
      _user_info = User.get_cached_user_info(user)
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919

      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
920
921

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

925
      Enum.each(["john", "jo", "j"], fn query ->
926
927
928
929
930
        assert user ==
                 User.search(query)
                 |> List.first()
                 |> Map.put(:search_rank, nil)
                 |> Map.put(:search_type, nil)
931
932
933
934
935
936
937
      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 ->
938
939
940
941
942
        assert user ==
                 User.search(query)
                 |> List.first()
                 |> Map.put(:search_rank, nil)
                 |> Map.put(:search_type, nil)
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
      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

969
970
971
972
973
974
    test "finds users, handling misspelled requests" do
      u1 = insert(:user, %{name: "lain"})

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

975
976
977
978
979
980
981
982
983
    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)

984
985
      assert [friend.id, follower.id, u2.id] --
               Enum.map(User.search("doe", resolve: false, for_user: u1), & &1.id) == []
986
    end
cascode's avatar
cascode committed
987
988
989
990
991
992

    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
993
994
               User.search("lain@pleroma.soykaf.com")
               |> List.first()
995
               |> Map.put(:search_rank, nil)
996
               |> Map.put(:search_type, nil)
cascode's avatar
cascode committed
997
    end
998
999
1000

    test "does not yield false-positive matches" do
      insert(:user, %{name: "John Doe"})
For faster browsing, not all history is shown. View entire blame