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

5
6
defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
  use Pleroma.Web.ConnCase
7
  use Oban.Testing, repo: Pleroma.Repo
8

Alexander Strizhakov's avatar
Alexander Strizhakov committed
9
  import ExUnit.CaptureLog
10
11
  import Mock
  import Pleroma.Factory
12
  import Swoosh.TestAssertions
Alexander Strizhakov's avatar
Alexander Strizhakov committed
13

Sergey Suprunenko's avatar
Sergey Suprunenko committed
14
  alias Pleroma.Activity
Alexander Strizhakov's avatar
Alexander Strizhakov committed
15
  alias Pleroma.Config
Maxim Filippov's avatar
Maxim Filippov committed
16
  alias Pleroma.HTML
17
  alias Pleroma.MFA
Maxim Filippov's avatar
Maxim Filippov committed
18
19
  alias Pleroma.ModerationLog
  alias Pleroma.Repo
20
  alias Pleroma.Tests.ObanHelpers
Haelwenn's avatar
Haelwenn committed
21
  alias Pleroma.User
Alexander Strizhakov's avatar
Alexander Strizhakov committed
22
  alias Pleroma.Web
23
  alias Pleroma.Web.ActivityPub.Relay
Sergey Suprunenko's avatar
Sergey Suprunenko committed
24
  alias Pleroma.Web.CommonAPI
25
  alias Pleroma.Web.MediaProxy
26

27
28
29
30
31
32
  setup_all do
    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)

    :ok
  end

33
34
35
36
37
38
39
40
41
42
  setup do
    admin = insert(:user, is_admin: true)
    token = insert(:oauth_admin_token, user: admin)

    conn =
      build_conn()
      |> assign(:user, admin)
      |> assign(:token, token)

    {:ok, %{admin: admin, token: token, conn: conn}}
43
44
  end

45
46
47
48
49
50
51
52
53
54
  test "with valid `admin_token` query parameter, skips OAuth scopes check" do
    clear_config([:admin_token], "password123")

    user = insert(:user)

    conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123")

    assert json_response(conn, 200)
  end

55
  describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
56
    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
57

58
59
    test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
         %{admin: admin} do
60
      user = insert(:user)
61
      url = "/api/pleroma/admin/users/#{user.nickname}"
62
63
64
65
66
67
68
69
70
71
72
73
74
75

      good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
      good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
      good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])

      bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
      bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
      bad_token3 = nil

      for good_token <- [good_token1, good_token2, good_token3] do
        conn =
          build_conn()
          |> assign(:user, admin)
          |> assign(:token, good_token)
76
          |> get(url)
77
78
79
80

        assert json_response(conn, 200)
      end

81
82
83
84
85
86
87
88
89
90
      for good_token <- [good_token1, good_token2, good_token3] do
        conn =
          build_conn()
          |> assign(:user, nil)
          |> assign(:token, good_token)
          |> get(url)

        assert json_response(conn, :forbidden)
      end

91
92
93
94
95
      for bad_token <- [bad_token1, bad_token2, bad_token3] do
        conn =
          build_conn()
          |> assign(:user, admin)
          |> assign(:token, bad_token)
96
          |> get(url)
97
98
99
100
101
102

        assert json_response(conn, :forbidden)
      end
    end
  end

103
  describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
104
    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

    test "GET /api/pleroma/admin/users/:nickname requires " <>
           "read:accounts or admin:read:accounts or broader scope",
         %{admin: admin} do
      user = insert(:user)
      url = "/api/pleroma/admin/users/#{user.nickname}"

      good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
      good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
      good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
      good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
      good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])

      good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]

      bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
      bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
      bad_token3 = nil

      for good_token <- good_tokens do
        conn =
          build_conn()
          |> assign(:user, admin)
          |> assign(:token, good_token)
          |> get(url)

        assert json_response(conn, 200)
      end

      for good_token <- good_tokens do
        conn =
          build_conn()
          |> assign(:user, nil)
          |> assign(:token, good_token)
          |> get(url)

        assert json_response(conn, :forbidden)
      end

      for bad_token <- [bad_token1, bad_token2, bad_token3] do
        conn =
          build_conn()
          |> assign(:user, admin)
          |> assign(:token, bad_token)
          |> get(url)

        assert json_response(conn, :forbidden)
      end
    end
  end

156
  describe "DELETE /api/pleroma/admin/users" do
157
    test "single user", %{admin: admin, conn: conn} do
lain's avatar
lain committed
158
      clear_config([:instance, :federating], true)
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
      user =
        insert(:user,
          avatar: %{"url" => [%{"href" => "https://someurl"}]},
          banner: %{"url" => [%{"href" => "https://somebanner"}]}
        )

      # Create some activities to check they got deleted later
      follower = insert(:user)
      {:ok, _} = CommonAPI.post(user, %{status: "test"})
      {:ok, _, _, _} = CommonAPI.follow(user, follower)
      {:ok, _, _, _} = CommonAPI.follow(follower, user)
      user = Repo.get(User, user.id)
      assert user.note_count == 1
      assert user.follower_count == 1
      assert user.following_count == 1
175
176
      refute user.deactivated

177
      with_mock Pleroma.Web.Federator,
178
179
        publish: fn _ -> nil end,
        perform: fn _, _ -> nil end do
180
181
182
183
        conn =
          conn
          |> put_req_header("accept", "application/json")
          |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
184

185
        ObanHelpers.perform_all()
Maxim Filippov's avatar
Maxim Filippov committed
186

187
        assert User.get_by_nickname(user.nickname).deactivated
188
189

        log_entry = Repo.one(ModerationLog)
Maxim Filippov's avatar
Maxim Filippov committed
190

191
192
        assert ModerationLog.get_log_entry_message(log_entry) ==
                 "@#{admin.nickname} deleted users: @#{user.nickname}"
Maxim Filippov's avatar
Maxim Filippov committed
193

194
195
        assert json_response(conn, 200) == [user.nickname]

196
197
198
        user = Repo.get(User, user.id)
        assert user.deactivated

199
200
201
202
203
204
        assert user.avatar == %{}
        assert user.banner == %{}
        assert user.note_count == 0
        assert user.follower_count == 0
        assert user.following_count == 0

205
206
        assert called(Pleroma.Web.Federator.publish(:_))
      end
207
208
    end

209
    test "multiple users", %{admin: admin, conn: conn} do
210
211
212
213
      user_one = insert(:user)
      user_two = insert(:user)

      conn =
214
        conn
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
        |> put_req_header("accept", "application/json")
        |> delete("/api/pleroma/admin/users", %{
          nicknames: [user_one.nickname, user_two.nickname]
        })

      log_entry = Repo.one(ModerationLog)

      assert ModerationLog.get_log_entry_message(log_entry) ==
               "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"

      response = json_response(conn, 200)
      assert response -- [user_one.nickname, user_two.nickname] == []
    end
  end

  describe "/api/pleroma/admin/users" do
231
    test "Create", %{conn: conn} do
232
      conn =
233
        conn
234
        |> put_req_header("accept", "application/json")
Sachin Joshi's avatar
Sachin Joshi committed
235
        |> post("/api/pleroma/admin/users", %{
236
237
238
239
240
          "users" => [
            %{
              "nickname" => "lain",
              "email" => "lain@example.org",
              "password" => "test"
241
242
243
244
245
            },
            %{
              "nickname" => "lain2",
              "email" => "lain2@example.org",
              "password" => "test"
246
247
            }
          ]
248
249
        })

250
251
      response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
      assert response == ["success", "success"]
Maxim Filippov's avatar
Maxim Filippov committed
252
253
254

      log_entry = Repo.one(ModerationLog)

Maxim Filippov's avatar
Maxim Filippov committed
255
      assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
256
257
    end

258
    test "Cannot create user with existing email", %{conn: conn} do
259
260
261
      user = insert(:user)

      conn =
262
        conn
263
264
265
266
267
268
269
270
271
272
273
        |> put_req_header("accept", "application/json")
        |> post("/api/pleroma/admin/users", %{
          "users" => [
            %{
              "nickname" => "lain",
              "email" => user.email,
              "password" => "test"
            }
          ]
        })

274
      assert json_response(conn, 409) == [
275
276
277
278
279
280
281
282
283
284
285
286
               %{
                 "code" => 409,
                 "data" => %{
                   "email" => user.email,
                   "nickname" => "lain"
                 },
                 "error" => "email has already been taken",
                 "type" => "error"
               }
             ]
    end

287
    test "Cannot create user with existing nickname", %{conn: conn} do
288
289
290
      user = insert(:user)

      conn =
291
        conn
292
293
294
295
296
297
298
299
300
301
302
        |> put_req_header("accept", "application/json")
        |> post("/api/pleroma/admin/users", %{
          "users" => [
            %{
              "nickname" => user.nickname,
              "email" => "someuser@plerama.social",
              "password" => "test"
            }
          ]
        })

303
      assert json_response(conn, 409) == [
304
305
306
307
308
309
310
311
312
313
               %{
                 "code" => 409,
                 "data" => %{
                   "email" => "someuser@plerama.social",
                   "nickname" => user.nickname
                 },
                 "error" => "nickname has already been taken",
                 "type" => "error"
               }
             ]
314
    end
315

316
    test "Multiple user creation works in transaction", %{conn: conn} do
317
318
319
      user = insert(:user)

      conn =
320
        conn
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
        |> put_req_header("accept", "application/json")
        |> post("/api/pleroma/admin/users", %{
          "users" => [
            %{
              "nickname" => "newuser",
              "email" => "newuser@pleroma.social",
              "password" => "test"
            },
            %{
              "nickname" => "lain",
              "email" => user.email,
              "password" => "test"
            }
          ]
        })

      assert json_response(conn, 409) == [
               %{
                 "code" => 409,
                 "data" => %{
                   "email" => user.email,
                   "nickname" => "lain"
                 },
                 "error" => "email has already been taken",
                 "type" => "error"
               },
               %{
                 "code" => 409,
                 "data" => %{
                   "email" => "newuser@pleroma.social",
                   "nickname" => "newuser"
                 },
                 "error" => "",
                 "type" => "error"
               }
             ]

      assert User.get_by_nickname("newuser") === nil
359
360
361
    end
  end

362
363
364
365
  describe "/api/pleroma/admin/users/:nickname" do
    test "Show", %{conn: conn} do
      user = insert(:user)

366
      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
367
368
369
370
371
372
373

      expected = %{
        "deactivated" => false,
        "id" => to_string(user.id),
        "local" => true,
        "nickname" => user.nickname,
        "roles" => %{"admin" => false, "moderator" => false},
374
375
        "tags" => [],
        "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
376
        "display_name" => HTML.strip_tags(user.name || user.nickname),
377
        "confirmation_pending" => false,
378
        "approval_pending" => false,
379
380
        "url" => user.ap_id,
        "registration_reason" => nil
381
382
383
384
385
386
387
388
      }

      assert expected == json_response(conn, 200)
    end

    test "when the user doesn't exist", %{conn: conn} do
      user = build(:user)

389
      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
390

391
      assert %{"error" => "Not found"} == json_response(conn, 404)
392
393
394
    end
  end

Sachin Joshi's avatar
Sachin Joshi committed
395
  describe "/api/pleroma/admin/users/follow" do
396
    test "allows to force-follow another user", %{admin: admin, conn: conn} do
397
398
399
      user = insert(:user)
      follower = insert(:user)

400
      conn
401
      |> put_req_header("accept", "application/json")
Sachin Joshi's avatar
Sachin Joshi committed
402
      |> post("/api/pleroma/admin/users/follow", %{
403
404
405
        "follower" => follower.nickname,
        "followed" => user.nickname
      })
406

minibikini's avatar
minibikini committed
407
408
      user = User.get_cached_by_id(user.id)
      follower = User.get_cached_by_id(follower.id)
409
410

      assert User.following?(follower, user)
Maxim Filippov's avatar
Maxim Filippov committed
411
412
413
414
415

      log_entry = Repo.one(ModerationLog)

      assert ModerationLog.get_log_entry_message(log_entry) ==
               "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
416
417
418
    end
  end

Sachin Joshi's avatar
Sachin Joshi committed
419
  describe "/api/pleroma/admin/users/unfollow" do
420
    test "allows to force-unfollow another user", %{admin: admin, conn: conn} do
421
422
423
424
425
      user = insert(:user)
      follower = insert(:user)

      User.follow(follower, user)

426
      conn
427
      |> put_req_header("accept", "application/json")
Sachin Joshi's avatar
Sachin Joshi committed
428
      |> post("/api/pleroma/admin/users/unfollow", %{
429
430
431
        "follower" => follower.nickname,
        "followed" => user.nickname
      })
432

minibikini's avatar
minibikini committed
433
434
      user = User.get_cached_by_id(user.id)
      follower = User.get_cached_by_id(follower.id)
435
436

      refute User.following?(follower, user)
Maxim Filippov's avatar
Maxim Filippov committed
437
438
439
440
441

      log_entry = Repo.one(ModerationLog)

      assert ModerationLog.get_log_entry_message(log_entry) ==
               "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
442
443
444
    end
  end

445
  describe "PUT /api/pleroma/admin/users/tag" do
446
    setup %{conn: conn} do
447
448
449
450
451
      user1 = insert(:user, %{tags: ["x"]})
      user2 = insert(:user, %{tags: ["y"]})
      user3 = insert(:user, %{tags: ["unchanged"]})

      conn =
452
        conn
453
        |> put_req_header("accept", "application/json")
Ivan Tashkinov's avatar
Ivan Tashkinov committed
454
        |> put(
455
456
          "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
            "#{user2.nickname}&tags[]=foo&tags[]=bar"
Ivan Tashkinov's avatar
Ivan Tashkinov committed
457
        )
458

459
      %{conn: conn, user1: user1, user2: user2, user3: user3}
460
461
    end

Ivan Tashkinov's avatar
Ivan Tashkinov committed
462
463
    test "it appends specified tags to users with specified nicknames", %{
      conn: conn,
Maxim Filippov's avatar
Maxim Filippov committed
464
      admin: admin,
Ivan Tashkinov's avatar
Ivan Tashkinov committed
465
466
467
      user1: user1,
      user2: user2
    } do
468
      assert empty_json_response(conn)
minibikini's avatar
minibikini committed
469
470
      assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
      assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
Maxim Filippov's avatar
Maxim Filippov committed
471
472
473
474
475
476
477
478
479
480
481
482

      log_entry = Repo.one(ModerationLog)

      users =
        [user1.nickname, user2.nickname]
        |> Enum.map(&"@#{&1}")
        |> Enum.join(", ")

      tags = ["foo", "bar"] |> Enum.join(", ")

      assert ModerationLog.get_log_entry_message(log_entry) ==
               "@#{admin.nickname} added tags: #{tags} to users: #{users}"
483
484
485
    end

    test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
486
      assert empty_json_response(conn)
minibikini's avatar
minibikini committed
487
      assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
488
489
490
    end
  end

491
  describe "DELETE /api/pleroma/admin/users/tag" do
492
    setup %{conn: conn} do
493
494
495
496
497
      user1 = insert(:user, %{tags: ["x"]})
      user2 = insert(:user, %{tags: ["y", "z"]})
      user3 = insert(:user, %{tags: ["unchanged"]})

      conn =
498
        conn
499
        |> put_req_header("accept", "application/json")
500
        |> delete(
501
502
          "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
            "#{user2.nickname}&tags[]=x&tags[]=z"
Ivan Tashkinov's avatar
Ivan Tashkinov committed
503
        )
504

505
      %{conn: conn, user1: user1, user2: user2, user3: user3}
506
507
    end

Ivan Tashkinov's avatar
Ivan Tashkinov committed
508
509
    test "it removes specified tags from users with specified nicknames", %{
      conn: conn,
Maxim Filippov's avatar
Maxim Filippov committed
510
      admin: admin,
Ivan Tashkinov's avatar
Ivan Tashkinov committed
511
512
513
      user1: user1,
      user2: user2
    } do
514
      assert empty_json_response(conn)
minibikini's avatar
minibikini committed
515
516
      assert User.get_cached_by_id(user1.id).tags == []
      assert User.get_cached_by_id(user2.id).tags == ["y"]
Maxim Filippov's avatar
Maxim Filippov committed
517
518
519
520
521
522
523
524
525
526
527
528

      log_entry = Repo.one(ModerationLog)

      users =
        [user1.nickname, user2.nickname]
        |> Enum.map(&"@#{&1}")
        |> Enum.join(", ")

      tags = ["x", "z"] |> Enum.join(", ")

      assert ModerationLog.get_log_entry_message(log_entry) ==
               "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
529
530
531
    end

    test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
532
      assert empty_json_response(conn)
minibikini's avatar
minibikini committed
533
      assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
534
535
536
    end
  end

Sachin Joshi's avatar
Sachin Joshi committed
537
  describe "/api/pleroma/admin/users/:nickname/permission_group" do
538
    test "GET is giving user_info", %{admin: admin, conn: conn} do
539
      conn =
540
        conn
541
        |> put_req_header("accept", "application/json")
Sachin Joshi's avatar
Sachin Joshi committed
542
        |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
543

lain's avatar
lain committed
544
545
546
547
      assert json_response(conn, 200) == %{
               "is_admin" => true,
               "is_moderator" => false
             }
548
549
    end

550
    test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do
551
552
553
      user = insert(:user)

      conn =
554
        conn
555
        |> put_req_header("accept", "application/json")
Sachin Joshi's avatar
Sachin Joshi committed
556
        |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
557

lain's avatar
lain committed
558
559
560
      assert json_response(conn, 200) == %{
               "is_admin" => true
             }
Maxim Filippov's avatar
Maxim Filippov committed
561
562
563
564
565

      log_entry = Repo.one(ModerationLog)

      assert ModerationLog.get_log_entry_message(log_entry) ==
               "@#{admin.nickname} made @#{user.nickname} admin"
566
567
    end

568
    test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do
569
570
      user_one = insert(:user)
      user_two = insert(:user)
571
572

      conn =
573
        conn
574
        |> put_req_header("accept", "application/json")
575
576
577
        |> post("/api/pleroma/admin/users/permission_group/admin", %{
          nicknames: [user_one.nickname, user_two.nickname]
        })
578

579
      assert json_response(conn, 200) == %{"is_admin" => true}
Maxim Filippov's avatar
Maxim Filippov committed
580
581
582
583

      log_entry = Repo.one(ModerationLog)

      assert ModerationLog.get_log_entry_message(log_entry) ==
584
               "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
585
586
    end

587
    test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do
588
      user = insert(:user, is_admin: true)
589
590

      conn =
591
        conn
592
        |> put_req_header("accept", "application/json")
Maxim Filippov's avatar
Maxim Filippov committed
593
        |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
594

595
      assert json_response(conn, 200) == %{"is_admin" => false}
Maxim Filippov's avatar
Maxim Filippov committed
596
597
598
599

      log_entry = Repo.one(ModerationLog)

      assert ModerationLog.get_log_entry_message(log_entry) ==
Maxim Filippov's avatar
Maxim Filippov committed
600
               "@#{admin.nickname} revoked admin role from @#{user.nickname}"
601
602
    end

603
604
605
606
    test "/:right DELETE, can remove from a permission group (multiple)", %{
      admin: admin,
      conn: conn
    } do
607
608
      user_one = insert(:user, is_admin: true)
      user_two = insert(:user, is_admin: true)
609
610

      conn =
611
        conn
612
        |> put_req_header("accept", "application/json")
613
614
615
        |> delete("/api/pleroma/admin/users/permission_group/admin", %{
          nicknames: [user_one.nickname, user_two.nickname]
        })
616

617
      assert json_response(conn, 200) == %{"is_admin" => false}
Maxim Filippov's avatar
Maxim Filippov committed
618
619
620
621

      log_entry = Repo.one(ModerationLog)

      assert ModerationLog.get_log_entry_message(log_entry) ==
622
623
624
               "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
                 user_two.nickname
               }"
625
626
627
    end
  end

628
  test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
lain's avatar
lain committed
629
    user = insert(:user)
630
631

    conn =
632
      conn
633
      |> put_req_header("accept", "application/json")
Sachin Joshi's avatar
Sachin Joshi committed
634
      |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
635

636
637
638
    resp = json_response(conn, 200)

    assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
639
  end
Maxim Filippov's avatar
Maxim Filippov committed
640

Maxim Filippov's avatar
Maxim Filippov committed
641
  describe "GET /api/pleroma/admin/users" do
Alexander Strizhakov's avatar
Alexander Strizhakov committed
642
    test "renders users array for the first page", %{conn: conn, admin: admin} do
643
644
      user = insert(:user, local: false, tags: ["foo", "bar"])
      user2 = insert(:user, approval_pending: true, registration_reason: "I'm a chill dude")
645

Alexander Strizhakov's avatar
Alexander Strizhakov committed
646
      conn = get(conn, "/api/pleroma/admin/users?page=1")
Maxim Filippov's avatar
Maxim Filippov committed
647

Maksim's avatar
Maksim committed
648
649
650
      users =
        [
          %{
651
            "deactivated" => admin.deactivated,
Maksim's avatar
Maksim committed
652
653
654
655
            "id" => admin.id,
            "nickname" => admin.nickname,
            "roles" => %{"admin" => true, "moderator" => false},
            "local" => true,
656
657
            "tags" => [],
            "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
658
            "display_name" => HTML.strip_tags(admin.name || admin.nickname),
659
            "confirmation_pending" => false,
660
            "approval_pending" => false,
661
662
            "url" => admin.ap_id,
            "registration_reason" => nil
Maksim's avatar
Maksim committed
663
664
          },
          %{
665
            "deactivated" => user.deactivated,
Maksim's avatar
Maksim committed
666
667
668
669
            "id" => user.id,
            "nickname" => user.nickname,
            "roles" => %{"admin" => false, "moderator" => false},
            "local" => false,
670
671
            "tags" => ["foo", "bar"],
            "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
672
            "display_name" => HTML.strip_tags(user.name || user.nickname),
673
            "confirmation_pending" => false,
674
            "approval_pending" => false,
675
            "url" => user.ap_id,
676
677
678
679
680
681
682
683
684
685
686
687
688
689
            "registration_reason" => nil
          },
          %{
            "deactivated" => user2.deactivated,
            "id" => user2.id,
            "nickname" => user2.nickname,
            "roles" => %{"admin" => false, "moderator" => false},
            "local" => true,
            "tags" => [],
            "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
            "display_name" => HTML.strip_tags(user2.name || user2.nickname),
            "confirmation_pending" => false,
            "approval_pending" => true,
            "url" => user2.ap_id,
690
            "registration_reason" => "I'm a chill dude"
Maksim's avatar
Maksim committed
691
692
693
694
          }
        ]
        |> Enum.sort_by(& &1["nickname"])

Maxim Filippov's avatar
Maxim Filippov committed
695
      assert json_response(conn, 200) == %{
696
               "count" => 3,
Maxim Filippov's avatar
Maxim Filippov committed
697
               "page_size" => 50,
Maksim's avatar
Maksim committed
698
               "users" => users
Maxim Filippov's avatar
Maxim Filippov committed
699
700
701
             }
    end

702
    test "pagination works correctly with service users", %{conn: conn} do
703
704
      service1 = User.get_or_create_service_actor_by_ap_id(Web.base_url() <> "/meido", "meido")

705
706
707
708
709
710
711
712
      insert_list(25, :user)

      assert %{"count" => 26, "page_size" => 10, "users" => users1} =
               conn
               |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"})
               |> json_response(200)

      assert Enum.count(users1) == 10
713
      assert service1 not in users1
714
715
716
717
718
719
720

      assert %{"count" => 26, "page_size" => 10, "users" => users2} =
               conn
               |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"})
               |> json_response(200)

      assert Enum.count(users2) == 10
721
      assert service1 not in users2
722
723
724
725
726
727
728

      assert %{"count" => 26, "page_size" => 10, "users" => users3} =
               conn
               |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"})
               |> json_response(200)

      assert Enum.count(users3) == 6
729
      assert service1 not in users3
730
731
    end

Alexander Strizhakov's avatar
Alexander Strizhakov committed
732
    test "renders empty array for the second page", %{conn: conn} do
Maxim Filippov's avatar
Maxim Filippov committed
733
      insert(:user)
Maxim Filippov's avatar
Maxim Filippov committed
734

Alexander Strizhakov's avatar
Alexander Strizhakov committed
735
      conn = get(conn, "/api/pleroma/admin/users?page=2")
Maxim Filippov's avatar
Maxim Filippov committed
736
737

      assert json_response(conn, 200) == %{
Maxim Filippov's avatar
Maxim Filippov committed
738
               "count" => 2,
Maxim Filippov's avatar
Maxim Filippov committed
739
740
741
742
               "page_size" => 50,
               "users" => []
             }
    end
Maxim Filippov's avatar
Maxim Filippov committed
743

Alexander Strizhakov's avatar
Alexander Strizhakov committed
744
    test "regular search", %{conn: conn} do
745
      user = insert(:user, nickname: "bob")
Maxim Filippov's avatar
Maxim Filippov committed
746

Alexander Strizhakov's avatar
Alexander Strizhakov committed
747
      conn = get(conn, "/api/pleroma/admin/users?query=bo")
748
749

      assert json_response(conn, 200) == %{
750
751
752
753
               "count" => 1,
               "page_size" => 50,
               "users" => [
                 %{
754
                   "deactivated" => user.deactivated,
755
                   "id" => user.id,
756
                   "nickname" => user.nickname,
757
                   "roles" => %{"admin" => false, "moderator" => false},
Maxim Filippov's avatar
Maxim Filippov committed
758
                   "local" => true,
759
760
                   "tags" => [],
                   "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
761
                   "display_name" => HTML.strip_tags(user.name || user.nickname),
762
                   "confirmation_pending" => false,
763
                   "approval_pending" => false,
764
765
                   "url" => user.ap_id,
                   "registration_reason" => nil
766
767
768
                 }
               ]
             }
769
770
    end

Alexander Strizhakov's avatar
Alexander Strizhakov committed
771
772
773
774
775
776
777
778
779
780
781
    test "search by domain", %{conn: conn} do
      user = insert(:user, nickname: "nickname@domain.com")
      insert(:user)

      conn = get(conn, "/api/pleroma/admin/users?query=domain.com")

      assert json_response(conn, 200) == %{
               "count" => 1,
               "page_size" => 50,
               "users" => [
                 %{
782
                   "deactivated" => user.deactivated,
Alexander Strizhakov's avatar
Alexander Strizhakov committed
783
784
785
786
                   "id" => user.id,
                   "nickname" => user.nickname,
                   "roles" => %{"admin" => false, "moderator" => false},
                   "local" => true,
787
788
                   "tags" => [],
                   "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
789
                   "display_name" => HTML.strip_tags(user.name || user.nickname),
790
                   "confirmation_pending" => false,
791
                   "approval_pending" => false,
792
793
                   "url" => user.ap_id,
                   "registration_reason" => nil
Alexander Strizhakov's avatar
Alexander Strizhakov committed
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
                 }
               ]
             }
    end

    test "search by full nickname", %{conn: conn} do
      user = insert(:user, nickname: "nickname@domain.com")
      insert(:user)

      conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")

      assert json_response(conn, 200) == %{
               "count" => 1,
               "page_size" => 50,
               "users" => [
                 %{
810
                   "deactivated" => user.deactivated,
Alexander Strizhakov's avatar
Alexander Strizhakov committed
811
812
813
814
                   "id" => user.id,
                   "nickname" => user.nickname,
                   "roles" => %{"admin" => false, "moderator" => false},
                   "local" => true,
815
816
                   "tags" => [],
                   "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
817
                   "display_name" => HTML.strip_tags(user.name || user.nickname),
818
                   "confirmation_pending" => false,
819
                   "approval_pending" => false,
820
821
                   "url" => user.ap_id,
                   "registration_reason" => nil
Alexander Strizhakov's avatar
Alexander Strizhakov committed
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
                 }
               ]
             }
    end

    test "search by display name", %{conn: conn} do
      user = insert(:user, name: "Display name")
      insert(:user)

      conn = get(conn, "/api/pleroma/admin/users?name=display")

      assert json_response(conn, 200) == %{
               "count" => 1,
               "page_size" => 50,
               "users" => [
                 %{
838
                   "deactivated" => user.deactivated,
Alexander Strizhakov's avatar
Alexander Strizhakov committed
839
840
841
842
                   "id" => user.id,
                   "nickname" => user.nickname,
                   "roles" => %{"admin" => false, "moderator" => false},
                   "local" => true,
843
844
                   "tags" => [],
                   "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
845
                   "display_name" => HTML.strip_tags(user.name || user.nickname),
846
                   "confirmation_pending" => false,
847
                   "approval_pending" => false,
848
849
                   "url" => user.ap_id,
                   "registration_reason" => nil
Alexander Strizhakov's avatar
Alexander Strizhakov committed
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
                 }
               ]
             }
    end

    test "search by email", %{conn: conn} do
      user = insert(:user, email: "email@example.com")
      insert(:user)

      conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")

      assert json_response(conn, 200) == %{
               "count" => 1,
               "page_size" => 50,
               "users" => [
                 %{
866
                   "deactivated" => user.deactivated,
Alexander Strizhakov's avatar
Alexander Strizhakov committed
867
868
869
870
                   "id" => user.id,
                   "nickname" => user.nickname,
                   "roles" => %{"admin" => false, "moderator" => false},
                   "local" => true,
871
872
                   "tags" => [],
                   "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
873
                   "display_name" => HTML.strip_tags(user.name || user.nickname),
874
                   "confirmation_pending" => false,
875
                   "approval_pending" => false,
876
877
                   "url" => user.ap_id,
                   "registration_reason" => nil
Alexander Strizhakov's avatar
Alexander Strizhakov committed
878
879
880
881
882
883
                 }
               ]
             }
    end

    test "regular search with page size", %{conn: conn} do
884
885
      user = insert(:user, nickname: "aalice")
      user2 = insert(:user, nickname: "alice")
Maxim Filippov's avatar
Maxim Filippov committed
886

Alexander Strizhakov's avatar
Alexander Strizhakov committed
887
      conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
Maxim Filippov's avatar
Maxim Filippov committed
888

Alexander Strizhakov's avatar
Alexander Strizhakov committed
889
      assert json_response(conn1, 200) == %{
Maxim Filippov's avatar
Maxim Filippov committed
890
891
892
893
               "count" => 2,
               "page_size" => 1,
               "users" => [
                 %{
894
                   "deactivated" => user.deactivated,
Maxim Filippov's avatar
Maxim Filippov committed
895
                   "id" => user.id,
896
                   "nickname" => user.nickname,
897
                   "roles" => %{"admin" => false, "moderator" => false},
Maxim Filippov's avatar
Maxim Filippov committed
898
                   "local" => true,
899
900
                   "tags" => [],
                   "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
901
                   "display_name" => HTML.strip_tags(user.name || user.nickname),
902
                   "confirmation_pending" => false,
903
                   "approval_pending" => false,
904
905
                   "url" => user.ap_id,
                   "registration_reason" => nil
Maxim Filippov's avatar
Maxim Filippov committed
906
907
908
909
                 }
               ]
             }

Alexander Strizhakov's avatar
Alexander Strizhakov committed
910
      conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
Maxim Filippov's avatar
Maxim Filippov committed
911

Alexander Strizhakov's avatar
Alexander Strizhakov committed
912
      assert json_response(conn2, 200) == %{
Maxim Filippov's avatar
Maxim Filippov committed
913
914
915
916
               "count" => 2,
               "page_size" => 1,
               "users" => [
                 %{
917
                   "deactivated" => user2.deactivated,
Maxim Filippov's avatar
Maxim Filippov committed
918
                   "id" => user2.id,
919
                   "nickname" => user2.nickname,
920
                   "roles" => %{"admin" => false, "moderator" => false},
Maxim Filippov's avatar
Maxim Filippov committed
921
                   "local" => true,
922
923
                   "tags" => [],
                   "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
924
                   "display_name" => HTML.strip_tags(user2.name || user2.nickname),
925
                   "confirmation_pending" => false,
926
                   "approval_pending" => false,
927
928
                   "url" => user2.ap_id,
                   "registration_reason" => nil
Maxim Filippov's avatar
Maxim Filippov committed
929
930
931
932
933
934
                 }
               ]
             }
    end

    test "only local users" do
935
      admin = insert(:user, is_admin: true, nickname: "john")
936
      token = insert(:oauth_admin_token, user: admin)
Maxim Filippov's avatar
Maxim Filippov committed
937
      user = insert(:user, nickname: "bob")
938
939
940
941
942
943

      insert(:user, nickname: "bobb", local: false)

      conn =
        build_conn()
        |> assign(:user, admin)
944
        |> assign(:token, token)
945
        |> get("/api/pleroma/admin/users?query=bo&filters=local")
946
947

      assert json_response(conn, 200) == %{
948
949
950
951
               "count" => 1,
               "page_size" => 50,
               "users" => [
                 %{
952
                   "deactivated" => user.deactivated,
953
                   "id" => user.id,
954
                   "nickname" => user.nickname,
955
                   "roles" => %{"admin" => false, "moderator" => false},
Maxim Filippov's avatar
Maxim Filippov committed
956
                   "local" => true,
957
958
                   "tags" => [],
                   "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
959
                   "display_name" => HTML.strip_tags(user.name || user.nickname),
960
                   "confirmation_pending" => false,
961
                   "approval_pending" => false,
962
963
                   "url" => user.ap_id,
                   "registration_reason" => nil
964
965
966
                 }
               ]
             }
967
    end
968

969
    test "only local users with no query", %{conn: conn, admin: old_admin} do
970
      admin = insert(:user, is_admin: true, nickname: "john")
971
972
973
974
      user = insert(:user, nickname: "bob")

      insert(:user, nickname: "bobb", local: false)

975
      conn = get(conn, "/api/pleroma/admin/users?filters=local")
976

Maksim's avatar
Maksim committed
977
978
979
      users =
        [
          %{
980
            "deactivated" => user.deactivated,
Maksim's avatar
Maksim committed
981
982
983
984
            "id" => user.id,
            "nickname" => user.nickname,
            "roles" => %{"admin" => false, "moderator" => false},
            "local" => true,
985
986
            "tags" => [],
            "avatar" => User.avatar_url(user) |> MediaProxy.url(),
Maxim Filippov's avatar
Maxim Filippov committed
987
            "display_name" => HTML.strip_tags(user.name || user.nickname),
988
            "confirmation_pending" => false,
989
            "approval_pending" => false,
990
991
            "url" => user.ap_id,
            "registration_reason" => nil
Maksim's avatar
Maksim committed
992
993
          },
          %{
994
            "deactivated" => admin.deactivated,
Maksim's avatar
Maksim committed
995
996
997
998
            "id" => admin.id,
            "nickname" => admin.nickname,
            "roles" => %{"admin" => true, "moderator" => false},
            "local" => true,
999
1000
            "tags" => [],
            "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
For faster browsing, not all history is shown. View entire blame