First
[anni] / test / pleroma / web / admin_api / controllers / user_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.AdminAPI.UserControllerTest do
6   use Pleroma.Web.ConnCase, async: false
7   use Oban.Testing, repo: Pleroma.Repo
8
9   import Mock
10   import Pleroma.Factory
11
12   alias Pleroma.HTML
13   alias Pleroma.ModerationLog
14   alias Pleroma.Repo
15   alias Pleroma.Tests.ObanHelpers
16   alias Pleroma.User
17   alias Pleroma.Web.ActivityPub.Relay
18   alias Pleroma.Web.CommonAPI
19   alias Pleroma.Web.Endpoint
20   alias Pleroma.Web.MediaProxy
21
22   setup_all do
23     Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
24
25     :ok
26   end
27
28   setup do
29     admin = insert(:user, is_admin: true)
30     token = insert(:oauth_admin_token, user: admin)
31
32     conn =
33       build_conn()
34       |> assign(:user, admin)
35       |> assign(:token, token)
36
37     {:ok, %{admin: admin, token: token, conn: conn}}
38   end
39
40   test "with valid `admin_token` query parameter, skips OAuth scopes check" do
41     clear_config([:instance, :admin_privileges], [:users_read])
42     clear_config([:admin_token], "password123")
43
44     user = insert(:user)
45
46     conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123")
47
48     assert json_response_and_validate_schema(conn, 200)
49   end
50
51   describe "DELETE /api/pleroma/admin/users" do
52     test "single user", %{admin: admin, conn: conn} do
53       clear_config([:instance, :federating], true)
54       clear_config([:instance, :admin_privileges], [:users_delete])
55
56       user =
57         insert(:user,
58           avatar: %{"url" => [%{"href" => "https://someurl"}]},
59           banner: %{"url" => [%{"href" => "https://somebanner"}]},
60           bio: "Hello world!",
61           name: "A guy"
62         )
63
64       # Create some activities to check they got deleted later
65       follower = insert(:user)
66       {:ok, _} = CommonAPI.post(user, %{status: "test"})
67       {:ok, _, _, _} = CommonAPI.follow(user, follower)
68       {:ok, _, _, _} = CommonAPI.follow(follower, user)
69       user = Repo.get(User, user.id)
70       assert user.note_count == 1
71       assert user.follower_count == 1
72       assert user.following_count == 1
73       assert user.is_active
74
75       with_mock Pleroma.Web.Federator,
76         publish: fn _ -> nil end,
77         perform: fn _, _ -> nil end do
78         conn =
79           conn
80           |> put_req_header("accept", "application/json")
81           |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
82
83         ObanHelpers.perform_all()
84
85         refute User.get_by_nickname(user.nickname).is_active
86
87         log_entry = Repo.one(ModerationLog)
88
89         assert ModerationLog.get_log_entry_message(log_entry) ==
90                  "@#{admin.nickname} deleted users: @#{user.nickname}"
91
92         assert json_response_and_validate_schema(conn, 200) == [user.nickname]
93
94         user = Repo.get(User, user.id)
95         refute user.is_active
96
97         assert user.avatar == %{}
98         assert user.banner == %{}
99         assert user.note_count == 0
100         assert user.follower_count == 0
101         assert user.following_count == 0
102         assert user.bio == ""
103         assert user.name == nil
104
105         assert called(Pleroma.Web.Federator.publish(:_))
106       end
107     end
108
109     test "multiple users", %{admin: admin, conn: conn} do
110       clear_config([:instance, :admin_privileges], [:users_delete])
111
112       user_one = insert(:user)
113       user_two = insert(:user)
114
115       response =
116         conn
117         |> put_req_header("accept", "application/json")
118         |> put_req_header("content-type", "application/json")
119         |> delete("/api/pleroma/admin/users", %{
120           nicknames: [user_one.nickname, user_two.nickname]
121         })
122         |> json_response_and_validate_schema(200)
123
124       log_entry = Repo.one(ModerationLog)
125
126       assert ModerationLog.get_log_entry_message(log_entry) ==
127                "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
128
129       assert response -- [user_one.nickname, user_two.nickname] == []
130     end
131
132     test "Needs privileged role", %{conn: conn} do
133       clear_config([:instance, :admin_privileges], [])
134
135       response =
136         conn
137         |> put_req_header("accept", "application/json")
138         |> delete("/api/pleroma/admin/users?nickname=nickname")
139
140       assert json_response(response, :forbidden)
141     end
142   end
143
144   describe "/api/pleroma/admin/users" do
145     test "Create", %{conn: conn} do
146       response =
147         conn
148         |> put_req_header("accept", "application/json")
149         |> put_req_header("content-type", "application/json")
150         |> post("/api/pleroma/admin/users", %{
151           "users" => [
152             %{
153               "nickname" => "lain",
154               "email" => "lain@example.org",
155               "password" => "test"
156             },
157             %{
158               "nickname" => "lain2",
159               "email" => "lain2@example.org",
160               "password" => "test"
161             }
162           ]
163         })
164         |> json_response_and_validate_schema(200)
165         |> Enum.map(&Map.get(&1, "type"))
166
167       assert response == ["success", "success"]
168
169       log_entry = Repo.one(ModerationLog)
170
171       assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
172     end
173
174     test "Cannot create user with existing email", %{conn: conn} do
175       user = insert(:user)
176
177       conn =
178         conn
179         |> put_req_header("accept", "application/json")
180         |> put_req_header("content-type", "application/json")
181         |> post("/api/pleroma/admin/users", %{
182           "users" => [
183             %{
184               "nickname" => "lain",
185               "email" => user.email,
186               "password" => "test"
187             }
188           ]
189         })
190
191       assert json_response_and_validate_schema(conn, 409) == [
192                %{
193                  "code" => 409,
194                  "data" => %{
195                    "email" => user.email,
196                    "nickname" => "lain"
197                  },
198                  "error" => "email has already been taken",
199                  "type" => "error"
200                }
201              ]
202     end
203
204     test "Cannot create user with existing nickname", %{conn: conn} do
205       user = insert(:user)
206
207       conn =
208         conn
209         |> put_req_header("accept", "application/json")
210         |> put_req_header("content-type", "application/json")
211         |> post("/api/pleroma/admin/users", %{
212           "users" => [
213             %{
214               "nickname" => user.nickname,
215               "email" => "someuser@plerama.social",
216               "password" => "test"
217             }
218           ]
219         })
220
221       assert json_response_and_validate_schema(conn, 409) == [
222                %{
223                  "code" => 409,
224                  "data" => %{
225                    "email" => "someuser@plerama.social",
226                    "nickname" => user.nickname
227                  },
228                  "error" => "nickname has already been taken",
229                  "type" => "error"
230                }
231              ]
232     end
233
234     test "Multiple user creation works in transaction", %{conn: conn} do
235       user = insert(:user)
236
237       conn =
238         conn
239         |> put_req_header("accept", "application/json")
240         |> put_req_header("content-type", "application/json")
241         |> post("/api/pleroma/admin/users", %{
242           "users" => [
243             %{
244               "nickname" => "newuser",
245               "email" => "newuser@pleroma.social",
246               "password" => "test"
247             },
248             %{
249               "nickname" => "lain",
250               "email" => user.email,
251               "password" => "test"
252             }
253           ]
254         })
255
256       assert json_response_and_validate_schema(conn, 409) == [
257                %{
258                  "code" => 409,
259                  "data" => %{
260                    "email" => user.email,
261                    "nickname" => "lain"
262                  },
263                  "error" => "email has already been taken",
264                  "type" => "error"
265                },
266                %{
267                  "code" => 409,
268                  "data" => %{
269                    "email" => "newuser@pleroma.social",
270                    "nickname" => "newuser"
271                  },
272                  "error" => "",
273                  "type" => "error"
274                }
275              ]
276
277       assert User.get_by_nickname("newuser") === nil
278     end
279   end
280
281   describe "GET /api/pleroma/admin/users/:nickname" do
282     setup do
283       clear_config([:instance, :admin_privileges], [:users_read])
284     end
285
286     test "returns 403 if not privileged with :users_read", %{conn: conn} do
287       clear_config([:instance, :admin_privileges], [])
288
289       conn = get(conn, "/api/pleroma/admin/users/user.nickname")
290
291       assert json_response(conn, :forbidden)
292     end
293
294     test "Show", %{conn: conn} do
295       user = insert(:user)
296
297       conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
298
299       assert user_response(user) == json_response_and_validate_schema(conn, 200)
300     end
301
302     test "when the user doesn't exist", %{conn: conn} do
303       user = build(:user)
304
305       conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
306
307       assert %{"error" => "Not found"} == json_response_and_validate_schema(conn, 404)
308     end
309
310     test "requires admin:read:accounts or broader scope",
311          %{admin: admin} do
312       user = insert(:user)
313       url = "/api/pleroma/admin/users/#{user.nickname}"
314
315       good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
316       good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
317       good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
318
319       bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
320       bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
321       bad_token3 = nil
322
323       for good_token <- [good_token1, good_token2, good_token3] do
324         conn =
325           build_conn()
326           |> assign(:user, admin)
327           |> assign(:token, good_token)
328           |> get(url)
329
330         assert json_response_and_validate_schema(conn, 200)
331       end
332
333       for good_token <- [good_token1, good_token2, good_token3] do
334         conn =
335           build_conn()
336           |> assign(:user, nil)
337           |> assign(:token, good_token)
338           |> get(url)
339
340         assert json_response(conn, :forbidden)
341       end
342
343       for bad_token <- [bad_token1, bad_token2, bad_token3] do
344         conn =
345           build_conn()
346           |> assign(:user, admin)
347           |> assign(:token, bad_token)
348           |> get(url)
349
350         assert json_response_and_validate_schema(conn, :forbidden)
351       end
352     end
353   end
354
355   describe "/api/pleroma/admin/users/follow" do
356     test "allows to force-follow another user", %{admin: admin, conn: conn} do
357       user = insert(:user)
358       follower = insert(:user)
359
360       conn
361       |> put_req_header("accept", "application/json")
362       |> put_req_header("content-type", "application/json")
363       |> post("/api/pleroma/admin/users/follow", %{
364         "follower" => follower.nickname,
365         "followed" => user.nickname
366       })
367
368       user = User.get_cached_by_id(user.id)
369       follower = User.get_cached_by_id(follower.id)
370
371       assert User.following?(follower, user)
372
373       log_entry = Repo.one(ModerationLog)
374
375       assert ModerationLog.get_log_entry_message(log_entry) ==
376                "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
377     end
378   end
379
380   describe "/api/pleroma/admin/users/unfollow" do
381     test "allows to force-unfollow another user", %{admin: admin, conn: conn} do
382       user = insert(:user)
383       follower = insert(:user)
384
385       User.follow(follower, user)
386
387       conn
388       |> put_req_header("accept", "application/json")
389       |> put_req_header("content-type", "application/json")
390       |> post("/api/pleroma/admin/users/unfollow", %{
391         "follower" => follower.nickname,
392         "followed" => user.nickname
393       })
394
395       user = User.get_cached_by_id(user.id)
396       follower = User.get_cached_by_id(follower.id)
397
398       refute User.following?(follower, user)
399
400       log_entry = Repo.one(ModerationLog)
401
402       assert ModerationLog.get_log_entry_message(log_entry) ==
403                "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
404     end
405   end
406
407   describe "GET /api/pleroma/admin/users" do
408     setup do
409       clear_config([:instance, :admin_privileges], [:users_read])
410     end
411
412     test "returns 403 if not privileged with :users_read", %{conn: conn} do
413       clear_config([:instance, :admin_privileges], [])
414
415       conn = get(conn, "/api/pleroma/admin/users?page=1")
416
417       assert json_response(conn, :forbidden)
418     end
419
420     test "renders users array for the first page", %{conn: conn, admin: admin} do
421       user = insert(:user, local: false, tags: ["foo", "bar"])
422       user2 = insert(:user, is_approved: false, registration_reason: "I'm a chill dude")
423
424       conn = get(conn, "/api/pleroma/admin/users?page=1")
425
426       users = [
427         user_response(
428           user2,
429           %{
430             "local" => true,
431             "is_approved" => false,
432             "registration_reason" => "I'm a chill dude",
433             "actor_type" => "Person"
434           }
435         ),
436         user_response(user, %{"local" => false, "tags" => ["foo", "bar"]}),
437         user_response(
438           admin,
439           %{"roles" => %{"admin" => true, "moderator" => false}}
440         )
441       ]
442
443       assert json_response_and_validate_schema(conn, 200) == %{
444                "count" => 3,
445                "page_size" => 50,
446                "users" => users
447              }
448     end
449
450     test "pagination works correctly with service users", %{conn: conn} do
451       service1 = User.get_or_create_service_actor_by_ap_id(Endpoint.url() <> "/meido", "meido")
452
453       insert_list(25, :user)
454
455       assert %{"count" => 26, "page_size" => 10, "users" => users1} =
456                conn
457                |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"})
458                |> json_response_and_validate_schema(200)
459
460       assert Enum.count(users1) == 10
461       assert service1 not in users1
462
463       assert %{"count" => 26, "page_size" => 10, "users" => users2} =
464                conn
465                |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"})
466                |> json_response_and_validate_schema(200)
467
468       assert Enum.count(users2) == 10
469       assert service1 not in users2
470
471       assert %{"count" => 26, "page_size" => 10, "users" => users3} =
472                conn
473                |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"})
474                |> json_response_and_validate_schema(200)
475
476       assert Enum.count(users3) == 6
477       assert service1 not in users3
478     end
479
480     test "renders empty array for the second page", %{conn: conn} do
481       insert(:user)
482
483       conn = get(conn, "/api/pleroma/admin/users?page=2")
484
485       assert json_response_and_validate_schema(conn, 200) == %{
486                "count" => 2,
487                "page_size" => 50,
488                "users" => []
489              }
490     end
491
492     test "regular search", %{conn: conn} do
493       user = insert(:user, nickname: "bob")
494
495       conn = get(conn, "/api/pleroma/admin/users?query=bo")
496
497       assert json_response_and_validate_schema(conn, 200) == %{
498                "count" => 1,
499                "page_size" => 50,
500                "users" => [user_response(user, %{"local" => true})]
501              }
502     end
503
504     test "search by domain", %{conn: conn} do
505       user = insert(:user, nickname: "nickname@domain.com")
506       insert(:user)
507
508       conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
509
510       assert json_response_and_validate_schema(conn, 200) == %{
511                "count" => 1,
512                "page_size" => 50,
513                "users" => [user_response(user)]
514              }
515     end
516
517     test "search by full nickname", %{conn: conn} do
518       user = insert(:user, nickname: "nickname@domain.com")
519       insert(:user)
520
521       conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
522
523       assert json_response_and_validate_schema(conn, 200) == %{
524                "count" => 1,
525                "page_size" => 50,
526                "users" => [user_response(user)]
527              }
528     end
529
530     test "search by display name", %{conn: conn} do
531       user = insert(:user, name: "Display name")
532       insert(:user)
533
534       conn = get(conn, "/api/pleroma/admin/users?name=display")
535
536       assert json_response_and_validate_schema(conn, 200) == %{
537                "count" => 1,
538                "page_size" => 50,
539                "users" => [user_response(user)]
540              }
541     end
542
543     test "search by email", %{conn: conn} do
544       user = insert(:user, email: "email@example.com")
545       insert(:user)
546
547       conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
548
549       assert json_response_and_validate_schema(conn, 200) == %{
550                "count" => 1,
551                "page_size" => 50,
552                "users" => [user_response(user)]
553              }
554     end
555
556     test "regular search with page size", %{conn: conn} do
557       user = insert(:user, nickname: "aalice")
558       user2 = insert(:user, nickname: "alice")
559
560       conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
561
562       assert json_response_and_validate_schema(conn1, 200) == %{
563                "count" => 2,
564                "page_size" => 1,
565                "users" => [user_response(user2)]
566              }
567
568       conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
569
570       assert json_response_and_validate_schema(conn2, 200) == %{
571                "count" => 2,
572                "page_size" => 1,
573                "users" => [user_response(user)]
574              }
575     end
576
577     test "only local users" do
578       admin = insert(:user, is_admin: true, nickname: "john")
579       token = insert(:oauth_admin_token, user: admin)
580       user = insert(:user, nickname: "bob")
581
582       insert(:user, nickname: "bobb", local: false)
583
584       conn =
585         build_conn()
586         |> assign(:user, admin)
587         |> assign(:token, token)
588         |> get("/api/pleroma/admin/users?query=bo&filters=local")
589
590       assert json_response_and_validate_schema(conn, 200) == %{
591                "count" => 1,
592                "page_size" => 50,
593                "users" => [user_response(user)]
594              }
595     end
596
597     test "only local users with no query", %{conn: conn, admin: old_admin} do
598       admin = insert(:user, is_admin: true, nickname: "john")
599       user = insert(:user, nickname: "bob")
600
601       insert(:user, nickname: "bobb", local: false)
602
603       conn = get(conn, "/api/pleroma/admin/users?filters=local")
604
605       users = [
606         user_response(user),
607         user_response(admin, %{
608           "roles" => %{"admin" => true, "moderator" => false}
609         }),
610         user_response(old_admin, %{
611           "is_active" => true,
612           "roles" => %{"admin" => true, "moderator" => false}
613         })
614       ]
615
616       assert json_response_and_validate_schema(conn, 200) == %{
617                "count" => 3,
618                "page_size" => 50,
619                "users" => users
620              }
621     end
622
623     test "only unconfirmed users", %{conn: conn} do
624       sad_user = insert(:user, nickname: "sadboy", is_confirmed: false)
625       old_user = insert(:user, nickname: "oldboy", is_confirmed: false)
626
627       insert(:user, nickname: "happyboy", is_approved: true)
628       insert(:user, is_confirmed: true)
629
630       result =
631         conn
632         |> get("/api/pleroma/admin/users?filters=unconfirmed")
633         |> json_response_and_validate_schema(200)
634
635       users =
636         Enum.map([old_user, sad_user], fn user ->
637           user_response(user, %{
638             "is_confirmed" => false,
639             "is_approved" => true
640           })
641         end)
642
643       assert result == %{"count" => 2, "page_size" => 50, "users" => users}
644     end
645
646     test "only unapproved users", %{conn: conn} do
647       user =
648         insert(:user,
649           nickname: "sadboy",
650           is_approved: false,
651           registration_reason: "Plz let me in!"
652         )
653
654       insert(:user, nickname: "happyboy", is_approved: true)
655
656       conn = get(conn, "/api/pleroma/admin/users?filters=need_approval")
657
658       users = [
659         user_response(
660           user,
661           %{"is_approved" => false, "registration_reason" => "Plz let me in!"}
662         )
663       ]
664
665       assert json_response_and_validate_schema(conn, 200) == %{
666                "count" => 1,
667                "page_size" => 50,
668                "users" => users
669              }
670     end
671
672     test "load only admins", %{conn: conn, admin: admin} do
673       second_admin = insert(:user, is_admin: true)
674       insert(:user)
675       insert(:user)
676
677       conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
678
679       users = [
680         user_response(second_admin, %{
681           "is_active" => true,
682           "roles" => %{"admin" => true, "moderator" => false}
683         }),
684         user_response(admin, %{
685           "is_active" => true,
686           "roles" => %{"admin" => true, "moderator" => false}
687         })
688       ]
689
690       assert json_response_and_validate_schema(conn, 200) == %{
691                "count" => 2,
692                "page_size" => 50,
693                "users" => users
694              }
695     end
696
697     test "load only moderators", %{conn: conn} do
698       moderator = insert(:user, is_moderator: true)
699       insert(:user)
700       insert(:user)
701
702       conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
703
704       assert json_response_and_validate_schema(conn, 200) == %{
705                "count" => 1,
706                "page_size" => 50,
707                "users" => [
708                  user_response(moderator, %{
709                    "is_active" => true,
710                    "roles" => %{"admin" => false, "moderator" => true}
711                  })
712                ]
713              }
714     end
715
716     test "load users with actor_type is Person", %{admin: admin, conn: conn} do
717       insert(:user, actor_type: "Service")
718       insert(:user, actor_type: "Application")
719
720       user1 = insert(:user)
721       user2 = insert(:user)
722
723       response =
724         conn
725         |> get(user_path(conn, :index), %{actor_types: ["Person"]})
726         |> json_response_and_validate_schema(200)
727
728       users = [
729         user_response(user2),
730         user_response(user1),
731         user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}})
732       ]
733
734       assert response == %{"count" => 3, "page_size" => 50, "users" => users}
735     end
736
737     test "load users with actor_type is Person and Service", %{admin: admin, conn: conn} do
738       user_service = insert(:user, actor_type: "Service")
739       insert(:user, actor_type: "Application")
740
741       user1 = insert(:user)
742       user2 = insert(:user)
743
744       response =
745         conn
746         |> get(user_path(conn, :index), %{actor_types: ["Person", "Service"]})
747         |> json_response_and_validate_schema(200)
748
749       users = [
750         user_response(user2),
751         user_response(user1),
752         user_response(user_service, %{"actor_type" => "Service"}),
753         user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}})
754       ]
755
756       assert response == %{"count" => 4, "page_size" => 50, "users" => users}
757     end
758
759     test "load users with actor_type is Service", %{conn: conn} do
760       user_service = insert(:user, actor_type: "Service")
761       insert(:user, actor_type: "Application")
762       insert(:user)
763       insert(:user)
764
765       response =
766         conn
767         |> get(user_path(conn, :index), %{actor_types: ["Service"]})
768         |> json_response_and_validate_schema(200)
769
770       users = [user_response(user_service, %{"actor_type" => "Service"})]
771
772       assert response == %{"count" => 1, "page_size" => 50, "users" => users}
773     end
774
775     test "load users with tags list", %{conn: conn} do
776       user1 = insert(:user, tags: ["first"])
777       user2 = insert(:user, tags: ["second"])
778       insert(:user)
779       insert(:user)
780
781       conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
782
783       users = [
784         user_response(user2, %{"tags" => ["second"]}),
785         user_response(user1, %{"tags" => ["first"]})
786       ]
787
788       assert json_response_and_validate_schema(conn, 200) == %{
789                "count" => 2,
790                "page_size" => 50,
791                "users" => users
792              }
793     end
794
795     test "`active` filters out users pending approval", %{token: token} do
796       insert(:user, is_approved: false)
797       %{id: user_id} = insert(:user, is_approved: true)
798       %{id: admin_id} = token.user
799
800       conn =
801         build_conn()
802         |> assign(:user, token.user)
803         |> assign(:token, token)
804         |> get("/api/pleroma/admin/users?filters=active")
805
806       assert %{
807                "count" => 2,
808                "page_size" => 50,
809                "users" => [
810                  %{"id" => ^user_id},
811                  %{"id" => ^admin_id}
812                ]
813              } = json_response_and_validate_schema(conn, 200)
814     end
815
816     test "it works with multiple filters" do
817       admin = insert(:user, nickname: "john", is_admin: true)
818       token = insert(:oauth_admin_token, user: admin)
819       user = insert(:user, nickname: "bob", local: false, is_active: false)
820
821       insert(:user, nickname: "ken", local: true, is_active: false)
822       insert(:user, nickname: "bobb", local: false, is_active: true)
823
824       conn =
825         build_conn()
826         |> assign(:user, admin)
827         |> assign(:token, token)
828         |> get("/api/pleroma/admin/users?filters=deactivated,external")
829
830       assert json_response_and_validate_schema(conn, 200) == %{
831                "count" => 1,
832                "page_size" => 50,
833                "users" => [user_response(user)]
834              }
835     end
836
837     test "it omits relay user", %{admin: admin, conn: conn} do
838       assert %User{} = Relay.get_actor()
839
840       conn = get(conn, "/api/pleroma/admin/users")
841
842       assert json_response_and_validate_schema(conn, 200) == %{
843                "count" => 1,
844                "page_size" => 50,
845                "users" => [
846                  user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}})
847                ]
848              }
849     end
850   end
851
852   test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do
853     clear_config([:instance, :admin_privileges], [:users_manage_invites])
854
855     user_one = insert(:user, is_approved: false)
856     user_two = insert(:user, is_approved: false)
857
858     conn =
859       conn
860       |> put_req_header("content-type", "application/json")
861       |> patch(
862         "/api/pleroma/admin/users/approve",
863         %{nicknames: [user_one.nickname, user_two.nickname]}
864       )
865
866     response = json_response_and_validate_schema(conn, 200)
867     assert Enum.map(response["users"], & &1["is_approved"]) == [true, true]
868
869     log_entry = Repo.one(ModerationLog)
870
871     assert ModerationLog.get_log_entry_message(log_entry) ==
872              "@#{admin.nickname} approved users: @#{user_one.nickname}, @#{user_two.nickname}"
873   end
874
875   test "PATCH /api/pleroma/admin/users/approve returns 403 if not privileged with :users_manage_invites",
876        %{conn: conn} do
877     clear_config([:instance, :admin_privileges], [])
878
879     conn =
880       conn
881       |> put_req_header("content-type", "application/json")
882       |> patch(
883         "/api/pleroma/admin/users/approve",
884         %{nicknames: ["user_one.nickname", "user_two.nickname"]}
885       )
886
887     assert json_response(conn, :forbidden)
888   end
889
890   test "PATCH /api/pleroma/admin/users/suggest", %{admin: admin, conn: conn} do
891     user1 = insert(:user, is_suggested: false)
892     user2 = insert(:user, is_suggested: false)
893
894     response =
895       conn
896       |> put_req_header("content-type", "application/json")
897       |> patch(
898         "/api/pleroma/admin/users/suggest",
899         %{nicknames: [user1.nickname, user2.nickname]}
900       )
901       |> json_response_and_validate_schema(200)
902
903     assert Enum.map(response["users"], & &1["is_suggested"]) == [true, true]
904     [user1, user2] = Repo.reload!([user1, user2])
905
906     assert user1.is_suggested
907     assert user2.is_suggested
908
909     log_entry = Repo.one(ModerationLog)
910
911     assert ModerationLog.get_log_entry_message(log_entry) ==
912              "@#{admin.nickname} added suggested users: @#{user1.nickname}, @#{user2.nickname}"
913   end
914
915   test "PATCH /api/pleroma/admin/users/unsuggest", %{admin: admin, conn: conn} do
916     user1 = insert(:user, is_suggested: true)
917     user2 = insert(:user, is_suggested: true)
918
919     response =
920       conn
921       |> put_req_header("content-type", "application/json")
922       |> patch(
923         "/api/pleroma/admin/users/unsuggest",
924         %{nicknames: [user1.nickname, user2.nickname]}
925       )
926       |> json_response_and_validate_schema(200)
927
928     assert Enum.map(response["users"], & &1["is_suggested"]) == [false, false]
929     [user1, user2] = Repo.reload!([user1, user2])
930
931     refute user1.is_suggested
932     refute user2.is_suggested
933
934     log_entry = Repo.one(ModerationLog)
935
936     assert ModerationLog.get_log_entry_message(log_entry) ==
937              "@#{admin.nickname} removed suggested users: @#{user1.nickname}, @#{user2.nickname}"
938   end
939
940   describe "user activation" do
941     test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
942       clear_config([:instance, :admin_privileges], [:users_manage_activation_state])
943
944       user_one = insert(:user, is_active: false)
945       user_two = insert(:user, is_active: false)
946
947       conn =
948         conn
949         |> put_req_header("content-type", "application/json")
950         |> patch(
951           "/api/pleroma/admin/users/activate",
952           %{nicknames: [user_one.nickname, user_two.nickname]}
953         )
954
955       response = json_response_and_validate_schema(conn, 200)
956       assert Enum.map(response["users"], & &1["is_active"]) == [true, true]
957
958       log_entry = Repo.one(ModerationLog)
959
960       assert ModerationLog.get_log_entry_message(log_entry) ==
961                "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
962     end
963
964     test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
965       clear_config([:instance, :admin_privileges], [:users_manage_activation_state])
966
967       user_one = insert(:user, is_active: true)
968       user_two = insert(:user, is_active: true)
969
970       conn =
971         conn
972         |> put_req_header("content-type", "application/json")
973         |> patch(
974           "/api/pleroma/admin/users/deactivate",
975           %{nicknames: [user_one.nickname, user_two.nickname]}
976         )
977
978       response = json_response_and_validate_schema(conn, 200)
979       assert Enum.map(response["users"], & &1["is_active"]) == [false, false]
980
981       log_entry = Repo.one(ModerationLog)
982
983       assert ModerationLog.get_log_entry_message(log_entry) ==
984                "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
985     end
986
987     test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
988       clear_config([:instance, :admin_privileges], [:users_manage_activation_state])
989
990       user = insert(:user)
991
992       conn =
993         conn
994         |> put_req_header("content-type", "application/json")
995         |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
996
997       assert json_response_and_validate_schema(conn, 200) ==
998                user_response(
999                  user,
1000                  %{"is_active" => !user.is_active}
1001                )
1002
1003       log_entry = Repo.one(ModerationLog)
1004
1005       assert ModerationLog.get_log_entry_message(log_entry) ==
1006                "@#{admin.nickname} deactivated users: @#{user.nickname}"
1007     end
1008
1009     test "it requires privileged role :statuses_activation to activate", %{conn: conn} do
1010       clear_config([:instance, :admin_privileges], [])
1011
1012       conn =
1013         conn
1014         |> put_req_header("content-type", "application/json")
1015         |> patch(
1016           "/api/pleroma/admin/users/activate",
1017           %{nicknames: ["user_one.nickname", "user_two.nickname"]}
1018         )
1019
1020       assert json_response(conn, :forbidden)
1021     end
1022
1023     test "it requires privileged role :statuses_activation to deactivate", %{conn: conn} do
1024       clear_config([:instance, :admin_privileges], [])
1025
1026       conn =
1027         conn
1028         |> put_req_header("content-type", "application/json")
1029         |> patch(
1030           "/api/pleroma/admin/users/deactivate",
1031           %{nicknames: ["user_one.nickname", "user_two.nickname"]}
1032         )
1033
1034       assert json_response(conn, :forbidden)
1035     end
1036
1037     test "it requires privileged role :statuses_activation to toggle activation", %{conn: conn} do
1038       clear_config([:instance, :admin_privileges], [])
1039
1040       conn =
1041         conn
1042         |> put_req_header("content-type", "application/json")
1043         |> patch("/api/pleroma/admin/users/user.nickname/toggle_activation")
1044
1045       assert json_response(conn, :forbidden)
1046     end
1047   end
1048
1049   defp user_response(user, attrs \\ %{}) do
1050     %{
1051       "is_active" => user.is_active,
1052       "id" => user.id,
1053       "email" => user.email,
1054       "nickname" => user.nickname,
1055       "roles" => %{"admin" => false, "moderator" => false},
1056       "local" => user.local,
1057       "tags" => [],
1058       "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1059       "display_name" => HTML.strip_tags(user.name || user.nickname),
1060       "is_confirmed" => true,
1061       "is_approved" => true,
1062       "is_suggested" => false,
1063       "url" => user.ap_id,
1064       "registration_reason" => nil,
1065       "actor_type" => "Person",
1066       "created_at" => CommonAPI.Utils.to_masto_date(user.inserted_at)
1067     }
1068     |> Map.merge(attrs)
1069   end
1070 end