user_test.exs 11.6 KB
Newer Older
lain's avatar
lain committed
1
2
defmodule Pleroma.UserTest do
  alias Pleroma.Builders.UserBuilder
lain's avatar
lain committed
3
  alias Pleroma.{User, Repo, Activity}
lain's avatar
lain committed
4
5
  alias Pleroma.Web.OStatus
  alias Pleroma.Web.Websub.WebsubClientSubscription
6
  alias Pleroma.Web.CommonAPI
lain's avatar
lain committed
7
8
  use Pleroma.DataCase

lain's avatar
lain committed
9
  import Pleroma.Factory
lain's avatar
lain committed
10
  import Ecto.Query
lain's avatar
lain committed
11

lain's avatar
lain committed
12
  test "ap_id returns the activity pub id for the user" do
lain's avatar
lain committed
13
    user = UserBuilder.build()
lain's avatar
lain committed
14

lain's avatar
lain committed
15
    expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
lain's avatar
lain committed
16
17
18
19
20

    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
21
    user = UserBuilder.build()
lain's avatar
lain committed
22
23
24
25
26

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

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

lain's avatar
lain committed
28
  test "follow takes a user and another user" do
lain's avatar
lain committed
29
30
    user = insert(:user)
    followed = insert(:user)
lain's avatar
lain committed
31

lain's avatar
lain committed
32
    {:ok, user} = User.follow(user, followed)
lain's avatar
lain committed
33
34
35

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

36
37
38
    followed = User.get_by_ap_id(followed.ap_id)
    assert followed.info["follower_count"] == 1

39
    assert User.ap_followers(followed) in user.following
lain's avatar
lain committed
40
  end
lain's avatar
lain committed
41

lain's avatar
lain committed
42
43
44
45
46
47
48
  test "can't follow a deactivated users" do
    user = insert(:user)
    followed = insert(:user, info: %{"deactivated" => true})

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

lain's avatar
lain committed
49
50
51
52
  # 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
53

lain's avatar
lain committed
54
  #   assert followed.local == false
lain's avatar
lain committed
55

lain's avatar
lain committed
56
57
  #   {:ok, user} = User.follow(user, followed)
  #   assert User.ap_followers(followed) in user.following
lain's avatar
lain committed
58

lain's avatar
lain committed
59
60
61
  #   query = from w in WebsubClientSubscription,
  #   where: w.topic == ^followed.info["topic"]
  #   websub = Repo.one(query)
lain's avatar
lain committed
62

lain's avatar
lain committed
63
64
  #   assert websub
  # end
lain's avatar
lain committed
65

lain's avatar
lain committed
66
  test "unfollow takes a user and another user" do
lain's avatar
lain committed
67
68
    followed = insert(:user)
    user = insert(:user, %{following: [User.ap_followers(followed)]})
lain's avatar
lain committed
69

lain's avatar
lain committed
70
    {:ok, user, _activity} = User.unfollow(user, followed)
lain's avatar
lain committed
71
72
73
74
75

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

    assert user.following == []
  end
76

77
78
79
80
81
  test "unfollow doesn't unfollow yourself" do
    user = insert(:user)

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

eal's avatar
eal committed
82
    user = Repo.get(User, user.id)
83
84
85
    assert user.following == [user.ap_id]
  end

86
  test "test if a user is following another user" do
lain's avatar
lain committed
87
88
    followed = insert(:user)
    user = insert(:user, %{following: [User.ap_followers(followed)]})
89
90
91
92

    assert User.following?(user, followed)
    refute User.following?(followed, user)
  end
lain's avatar
lain committed
93
94
95
96
97
98
99
100
101
102
103

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

vaartis's avatar
vaartis committed
104
    test "it requires an email, name, nickname and password, bio is optional" do
lain's avatar
lain committed
105
      @full_user_data
lain's avatar
lain committed
106
107
      |> Map.keys()
      |> Enum.each(fn key ->
lain's avatar
lain committed
108
109
        params = Map.delete(@full_user_data, key)
        changeset = User.register_changeset(%User{}, params)
vaartis's avatar
vaartis committed
110

lain's avatar
lain committed
111
        assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
lain's avatar
lain committed
112
113
114
115
116
117
118
119
120
121
      end)
    end

    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
122
123
124
125
126

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

127
      assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
lain's avatar
lain committed
128
129
    end
  end
lain's avatar
lain committed
130
131
132
133
134
135
136
137
138

  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

139
140
141
142
143
144
145
    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

lain's avatar
lain committed
146
147
148
149
150
151
152
153
154
    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
155
156
157
158
159

    test "returns nil for nonexistant local user" do
      fetched_user = User.get_or_fetch_by_nickname("nonexistant")
      assert fetched_user == nil
    end
lain's avatar
lain committed
160
  end
161
162
163

  test "returns an ap_id for a user" do
    user = insert(:user)
lain's avatar
lain committed
164
165
166
167
168
169
170

    assert User.ap_id(user) ==
             Pleroma.Web.Router.Helpers.o_status_url(
               Pleroma.Web.Endpoint,
               :feed_redirect,
               user.nickname
             )
171
172
173
174
  end

  test "returns an ap_followers link for a user" do
    user = insert(:user)
lain's avatar
lain committed
175
176
177
178
179
180
181

    assert User.ap_followers(user) ==
             Pleroma.Web.Router.Helpers.o_status_url(
               Pleroma.Web.Endpoint,
               :feed_redirect,
               user.nickname
             ) <> "/followers"
182
  end
lain's avatar
lain committed
183
184
185
186
187
188
189

  describe "remote user creation changeset" do
    @valid_remote %{
      bio: "hello",
      name: "Someone",
      nickname: "a@b.de",
      ap_id: "http...",
lain's avatar
lain committed
190
191
      info: %{some: "info"},
      avatar: %{some: "avatar"}
lain's avatar
lain committed
192
193
194
195
196
197
198
    }

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

199
200
201
    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
202
203
      assert cs.changes.follower_address ==
               User.ap_followers(%User{nickname: @valid_remote[:nickname]})
204
205
    end

lain's avatar
lain committed
206
207
    test "it enforces the fqn format for nicknames" do
      cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
lain's avatar
lain committed
208
209
      assert cs.changes.local == false
      assert cs.changes.avatar
lain's avatar
lain committed
210
211
212
213
      refute cs.valid?
    end

    test "it has required fields" do
lain's avatar
lain committed
214
      [:name, :nickname, :ap_id]
lain's avatar
lain committed
215
      |> Enum.each(fn field ->
lain's avatar
lain committed
216
217
218
219
220
221
        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
222
      [bio: 5000, name: 100]
lain's avatar
lain committed
223
      |> Enum.each(fn {field, size} ->
lain's avatar
lain committed
224
225
226
227
228
229
230
231
232
233
        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
234
235
236
237
238
239
240
241
242
243
244
245
246

  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
247
248
249
      assert Enum.member?(res, follower_one)
      assert Enum.member?(res, follower_two)
      refute Enum.member?(res, not_follower)
lain's avatar
lain committed
250
251
252
253
254
255
256
257
258
259
260
261
262
    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)

263
264
      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
265
266
267
      assert Enum.member?(res, followed_one)
      assert Enum.member?(res, followed_two)
      refute Enum.member?(res, not_followed)
lain's avatar
lain committed
268
269
    end
  end
270
271
272
273
274
275
276
277
278
279
280
281
282
283

  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"])

      assert user.info["note_count"] == nil

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

      assert user.info["note_count"] == 1
    end

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    test "it increases the info->note_count property" do
      note = insert(:note)
      user = User.get_by_ap_id(note.data["actor"])

      assert user.info["note_count"] == nil

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

      assert user.info["note_count"] == 1

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

      assert user.info["note_count"] == 2
    end

299
300
301
302
303
304
305
306
307
308
309
310
311
    test "it sets the info->follower_count property" do
      user = insert(:user)
      follower = insert(:user)

      User.follow(follower, user)

      assert user.info["follower_count"] == nil

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

      assert user.info["follower_count"] == 1
    end
  end
lain's avatar
lain committed
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

  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
  end
335
336
337
338
339
340
341

  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
342
343
344
345
346

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

    assert [addressed] == User.get_recipients_from_activity(activity)

    {:ok, user} = User.follow(user, actor)
lain's avatar
lain committed
351
    {:ok, _user_two} = User.follow(user_two, actor)
352
353
354
355
356
    recipients = User.get_recipients_from_activity(activity)
    assert length(recipients) == 2
    assert user in recipients
    assert addressed in recipients
  end
lain's avatar
lain committed
357

lain's avatar
lain committed
358
359
360
361
362
363
  test ".deactivate deactivates a user" do
    user = insert(:user)
    assert false == !!user.info["deactivated"]
    {:ok, user} = User.deactivate(user)
    assert true == user.info["deactivated"]
  end
lain's avatar
lain committed
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

  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)

    :ok = User.delete(user)

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

    assert user.info["deactivated"]

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

lain's avatar
lain committed
391
392
393
    # TODO: Remove favorites, repeats, delete activities.

    refute Repo.get(Activity, activity.id)
lain's avatar
lain committed
394
  end
395
396
397
398

  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
399
400
401

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

    assert {:ok, %User{}} = User.insert_or_update_user(data)
  end
lain's avatar
lain committed
406
end