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