Merge branch 'features/profile-fields-emojo' into 'develop'
[akkoma] / test / web / admin_api / controllers / admin_api_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
6 use Pleroma.Web.ConnCase
7 use Oban.Testing, repo: Pleroma.Repo
8
9 import ExUnit.CaptureLog
10 import Mock
11 import Pleroma.Factory
12
13 alias Pleroma.Activity
14 alias Pleroma.Config
15 alias Pleroma.HTML
16 alias Pleroma.MFA
17 alias Pleroma.ModerationLog
18 alias Pleroma.Repo
19 alias Pleroma.Tests.ObanHelpers
20 alias Pleroma.User
21 alias Pleroma.Web
22 alias Pleroma.Web.ActivityPub.Relay
23 alias Pleroma.Web.CommonAPI
24 alias Pleroma.Web.MediaProxy
25
26 setup_all do
27 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
28
29 :ok
30 end
31
32 setup do
33 admin = insert(:user, is_admin: true)
34 token = insert(:oauth_admin_token, user: admin)
35
36 conn =
37 build_conn()
38 |> assign(:user, admin)
39 |> assign(:token, token)
40
41 {:ok, %{admin: admin, token: token, conn: conn}}
42 end
43
44 describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
45 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
46
47 test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
48 %{admin: admin} do
49 user = insert(:user)
50 url = "/api/pleroma/admin/users/#{user.nickname}"
51
52 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
53 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
54 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
55
56 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
57 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
58 bad_token3 = nil
59
60 for good_token <- [good_token1, good_token2, good_token3] do
61 conn =
62 build_conn()
63 |> assign(:user, admin)
64 |> assign(:token, good_token)
65 |> get(url)
66
67 assert json_response(conn, 200)
68 end
69
70 for good_token <- [good_token1, good_token2, good_token3] do
71 conn =
72 build_conn()
73 |> assign(:user, nil)
74 |> assign(:token, good_token)
75 |> get(url)
76
77 assert json_response(conn, :forbidden)
78 end
79
80 for bad_token <- [bad_token1, bad_token2, bad_token3] do
81 conn =
82 build_conn()
83 |> assign(:user, admin)
84 |> assign(:token, bad_token)
85 |> get(url)
86
87 assert json_response(conn, :forbidden)
88 end
89 end
90 end
91
92 describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
93 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
94
95 test "GET /api/pleroma/admin/users/:nickname requires " <>
96 "read:accounts or admin:read:accounts or broader scope",
97 %{admin: admin} do
98 user = insert(:user)
99 url = "/api/pleroma/admin/users/#{user.nickname}"
100
101 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
102 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
103 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
104 good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
105 good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])
106
107 good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]
108
109 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
110 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
111 bad_token3 = nil
112
113 for good_token <- good_tokens do
114 conn =
115 build_conn()
116 |> assign(:user, admin)
117 |> assign(:token, good_token)
118 |> get(url)
119
120 assert json_response(conn, 200)
121 end
122
123 for good_token <- good_tokens do
124 conn =
125 build_conn()
126 |> assign(:user, nil)
127 |> assign(:token, good_token)
128 |> get(url)
129
130 assert json_response(conn, :forbidden)
131 end
132
133 for bad_token <- [bad_token1, bad_token2, bad_token3] do
134 conn =
135 build_conn()
136 |> assign(:user, admin)
137 |> assign(:token, bad_token)
138 |> get(url)
139
140 assert json_response(conn, :forbidden)
141 end
142 end
143 end
144
145 describe "DELETE /api/pleroma/admin/users" do
146 test "single user", %{admin: admin, conn: conn} do
147 user = insert(:user)
148 clear_config([:instance, :federating], true)
149
150 with_mock Pleroma.Web.Federator,
151 publish: fn _ -> nil end do
152 conn =
153 conn
154 |> put_req_header("accept", "application/json")
155 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
156
157 ObanHelpers.perform_all()
158
159 assert User.get_by_nickname(user.nickname).deactivated
160
161 log_entry = Repo.one(ModerationLog)
162
163 assert ModerationLog.get_log_entry_message(log_entry) ==
164 "@#{admin.nickname} deleted users: @#{user.nickname}"
165
166 assert json_response(conn, 200) == [user.nickname]
167
168 assert called(Pleroma.Web.Federator.publish(:_))
169 end
170 end
171
172 test "multiple users", %{admin: admin, conn: conn} do
173 user_one = insert(:user)
174 user_two = insert(:user)
175
176 conn =
177 conn
178 |> put_req_header("accept", "application/json")
179 |> delete("/api/pleroma/admin/users", %{
180 nicknames: [user_one.nickname, user_two.nickname]
181 })
182
183 log_entry = Repo.one(ModerationLog)
184
185 assert ModerationLog.get_log_entry_message(log_entry) ==
186 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
187
188 response = json_response(conn, 200)
189 assert response -- [user_one.nickname, user_two.nickname] == []
190 end
191 end
192
193 describe "/api/pleroma/admin/users" do
194 test "Create", %{conn: conn} do
195 conn =
196 conn
197 |> put_req_header("accept", "application/json")
198 |> post("/api/pleroma/admin/users", %{
199 "users" => [
200 %{
201 "nickname" => "lain",
202 "email" => "lain@example.org",
203 "password" => "test"
204 },
205 %{
206 "nickname" => "lain2",
207 "email" => "lain2@example.org",
208 "password" => "test"
209 }
210 ]
211 })
212
213 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
214 assert response == ["success", "success"]
215
216 log_entry = Repo.one(ModerationLog)
217
218 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
219 end
220
221 test "Cannot create user with existing email", %{conn: conn} do
222 user = insert(:user)
223
224 conn =
225 conn
226 |> put_req_header("accept", "application/json")
227 |> post("/api/pleroma/admin/users", %{
228 "users" => [
229 %{
230 "nickname" => "lain",
231 "email" => user.email,
232 "password" => "test"
233 }
234 ]
235 })
236
237 assert json_response(conn, 409) == [
238 %{
239 "code" => 409,
240 "data" => %{
241 "email" => user.email,
242 "nickname" => "lain"
243 },
244 "error" => "email has already been taken",
245 "type" => "error"
246 }
247 ]
248 end
249
250 test "Cannot create user with existing nickname", %{conn: conn} do
251 user = insert(:user)
252
253 conn =
254 conn
255 |> put_req_header("accept", "application/json")
256 |> post("/api/pleroma/admin/users", %{
257 "users" => [
258 %{
259 "nickname" => user.nickname,
260 "email" => "someuser@plerama.social",
261 "password" => "test"
262 }
263 ]
264 })
265
266 assert json_response(conn, 409) == [
267 %{
268 "code" => 409,
269 "data" => %{
270 "email" => "someuser@plerama.social",
271 "nickname" => user.nickname
272 },
273 "error" => "nickname has already been taken",
274 "type" => "error"
275 }
276 ]
277 end
278
279 test "Multiple user creation works in transaction", %{conn: conn} do
280 user = insert(:user)
281
282 conn =
283 conn
284 |> put_req_header("accept", "application/json")
285 |> post("/api/pleroma/admin/users", %{
286 "users" => [
287 %{
288 "nickname" => "newuser",
289 "email" => "newuser@pleroma.social",
290 "password" => "test"
291 },
292 %{
293 "nickname" => "lain",
294 "email" => user.email,
295 "password" => "test"
296 }
297 ]
298 })
299
300 assert json_response(conn, 409) == [
301 %{
302 "code" => 409,
303 "data" => %{
304 "email" => user.email,
305 "nickname" => "lain"
306 },
307 "error" => "email has already been taken",
308 "type" => "error"
309 },
310 %{
311 "code" => 409,
312 "data" => %{
313 "email" => "newuser@pleroma.social",
314 "nickname" => "newuser"
315 },
316 "error" => "",
317 "type" => "error"
318 }
319 ]
320
321 assert User.get_by_nickname("newuser") === nil
322 end
323 end
324
325 describe "/api/pleroma/admin/users/:nickname" do
326 test "Show", %{conn: conn} do
327 user = insert(:user)
328
329 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
330
331 expected = %{
332 "deactivated" => false,
333 "id" => to_string(user.id),
334 "local" => true,
335 "nickname" => user.nickname,
336 "roles" => %{"admin" => false, "moderator" => false},
337 "tags" => [],
338 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
339 "display_name" => HTML.strip_tags(user.name || user.nickname),
340 "confirmation_pending" => false,
341 "url" => user.ap_id
342 }
343
344 assert expected == json_response(conn, 200)
345 end
346
347 test "when the user doesn't exist", %{conn: conn} do
348 user = build(:user)
349
350 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
351
352 assert %{"error" => "Not found"} == json_response(conn, 404)
353 end
354 end
355
356 describe "/api/pleroma/admin/users/follow" do
357 test "allows to force-follow another user", %{admin: admin, conn: conn} do
358 user = insert(:user)
359 follower = insert(:user)
360
361 conn
362 |> put_req_header("accept", "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 |> post("/api/pleroma/admin/users/unfollow", %{
390 "follower" => follower.nickname,
391 "followed" => user.nickname
392 })
393
394 user = User.get_cached_by_id(user.id)
395 follower = User.get_cached_by_id(follower.id)
396
397 refute User.following?(follower, user)
398
399 log_entry = Repo.one(ModerationLog)
400
401 assert ModerationLog.get_log_entry_message(log_entry) ==
402 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
403 end
404 end
405
406 describe "PUT /api/pleroma/admin/users/tag" do
407 setup %{conn: conn} do
408 user1 = insert(:user, %{tags: ["x"]})
409 user2 = insert(:user, %{tags: ["y"]})
410 user3 = insert(:user, %{tags: ["unchanged"]})
411
412 conn =
413 conn
414 |> put_req_header("accept", "application/json")
415 |> put(
416 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
417 "#{user2.nickname}&tags[]=foo&tags[]=bar"
418 )
419
420 %{conn: conn, user1: user1, user2: user2, user3: user3}
421 end
422
423 test "it appends specified tags to users with specified nicknames", %{
424 conn: conn,
425 admin: admin,
426 user1: user1,
427 user2: user2
428 } do
429 assert json_response(conn, :no_content)
430 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
431 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
432
433 log_entry = Repo.one(ModerationLog)
434
435 users =
436 [user1.nickname, user2.nickname]
437 |> Enum.map(&"@#{&1}")
438 |> Enum.join(", ")
439
440 tags = ["foo", "bar"] |> Enum.join(", ")
441
442 assert ModerationLog.get_log_entry_message(log_entry) ==
443 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
444 end
445
446 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
447 assert json_response(conn, :no_content)
448 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
449 end
450 end
451
452 describe "DELETE /api/pleroma/admin/users/tag" do
453 setup %{conn: conn} do
454 user1 = insert(:user, %{tags: ["x"]})
455 user2 = insert(:user, %{tags: ["y", "z"]})
456 user3 = insert(:user, %{tags: ["unchanged"]})
457
458 conn =
459 conn
460 |> put_req_header("accept", "application/json")
461 |> delete(
462 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
463 "#{user2.nickname}&tags[]=x&tags[]=z"
464 )
465
466 %{conn: conn, user1: user1, user2: user2, user3: user3}
467 end
468
469 test "it removes specified tags from users with specified nicknames", %{
470 conn: conn,
471 admin: admin,
472 user1: user1,
473 user2: user2
474 } do
475 assert json_response(conn, :no_content)
476 assert User.get_cached_by_id(user1.id).tags == []
477 assert User.get_cached_by_id(user2.id).tags == ["y"]
478
479 log_entry = Repo.one(ModerationLog)
480
481 users =
482 [user1.nickname, user2.nickname]
483 |> Enum.map(&"@#{&1}")
484 |> Enum.join(", ")
485
486 tags = ["x", "z"] |> Enum.join(", ")
487
488 assert ModerationLog.get_log_entry_message(log_entry) ==
489 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
490 end
491
492 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
493 assert json_response(conn, :no_content)
494 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
495 end
496 end
497
498 describe "/api/pleroma/admin/users/:nickname/permission_group" do
499 test "GET is giving user_info", %{admin: admin, conn: conn} do
500 conn =
501 conn
502 |> put_req_header("accept", "application/json")
503 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
504
505 assert json_response(conn, 200) == %{
506 "is_admin" => true,
507 "is_moderator" => false
508 }
509 end
510
511 test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do
512 user = insert(:user)
513
514 conn =
515 conn
516 |> put_req_header("accept", "application/json")
517 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
518
519 assert json_response(conn, 200) == %{
520 "is_admin" => true
521 }
522
523 log_entry = Repo.one(ModerationLog)
524
525 assert ModerationLog.get_log_entry_message(log_entry) ==
526 "@#{admin.nickname} made @#{user.nickname} admin"
527 end
528
529 test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do
530 user_one = insert(:user)
531 user_two = insert(:user)
532
533 conn =
534 conn
535 |> put_req_header("accept", "application/json")
536 |> post("/api/pleroma/admin/users/permission_group/admin", %{
537 nicknames: [user_one.nickname, user_two.nickname]
538 })
539
540 assert json_response(conn, 200) == %{"is_admin" => true}
541
542 log_entry = Repo.one(ModerationLog)
543
544 assert ModerationLog.get_log_entry_message(log_entry) ==
545 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
546 end
547
548 test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do
549 user = insert(:user, is_admin: true)
550
551 conn =
552 conn
553 |> put_req_header("accept", "application/json")
554 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
555
556 assert json_response(conn, 200) == %{"is_admin" => false}
557
558 log_entry = Repo.one(ModerationLog)
559
560 assert ModerationLog.get_log_entry_message(log_entry) ==
561 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
562 end
563
564 test "/:right DELETE, can remove from a permission group (multiple)", %{
565 admin: admin,
566 conn: conn
567 } do
568 user_one = insert(:user, is_admin: true)
569 user_two = insert(:user, is_admin: true)
570
571 conn =
572 conn
573 |> put_req_header("accept", "application/json")
574 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
575 nicknames: [user_one.nickname, user_two.nickname]
576 })
577
578 assert json_response(conn, 200) == %{"is_admin" => false}
579
580 log_entry = Repo.one(ModerationLog)
581
582 assert ModerationLog.get_log_entry_message(log_entry) ==
583 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
584 user_two.nickname
585 }"
586 end
587 end
588
589 test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
590 user = insert(:user)
591
592 conn =
593 conn
594 |> put_req_header("accept", "application/json")
595 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
596
597 resp = json_response(conn, 200)
598
599 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
600 end
601
602 describe "GET /api/pleroma/admin/users" do
603 test "renders users array for the first page", %{conn: conn, admin: admin} do
604 user = insert(:user, local: false, tags: ["foo", "bar"])
605 conn = get(conn, "/api/pleroma/admin/users?page=1")
606
607 users =
608 [
609 %{
610 "deactivated" => admin.deactivated,
611 "id" => admin.id,
612 "nickname" => admin.nickname,
613 "roles" => %{"admin" => true, "moderator" => false},
614 "local" => true,
615 "tags" => [],
616 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
617 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
618 "confirmation_pending" => false,
619 "url" => admin.ap_id
620 },
621 %{
622 "deactivated" => user.deactivated,
623 "id" => user.id,
624 "nickname" => user.nickname,
625 "roles" => %{"admin" => false, "moderator" => false},
626 "local" => false,
627 "tags" => ["foo", "bar"],
628 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
629 "display_name" => HTML.strip_tags(user.name || user.nickname),
630 "confirmation_pending" => false,
631 "url" => user.ap_id
632 }
633 ]
634 |> Enum.sort_by(& &1["nickname"])
635
636 assert json_response(conn, 200) == %{
637 "count" => 2,
638 "page_size" => 50,
639 "users" => users
640 }
641 end
642
643 test "pagination works correctly with service users", %{conn: conn} do
644 service1 = User.get_or_create_service_actor_by_ap_id(Web.base_url() <> "/meido", "meido")
645
646 insert_list(25, :user)
647
648 assert %{"count" => 26, "page_size" => 10, "users" => users1} =
649 conn
650 |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"})
651 |> json_response(200)
652
653 assert Enum.count(users1) == 10
654 assert service1 not in users1
655
656 assert %{"count" => 26, "page_size" => 10, "users" => users2} =
657 conn
658 |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"})
659 |> json_response(200)
660
661 assert Enum.count(users2) == 10
662 assert service1 not in users2
663
664 assert %{"count" => 26, "page_size" => 10, "users" => users3} =
665 conn
666 |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"})
667 |> json_response(200)
668
669 assert Enum.count(users3) == 6
670 assert service1 not in users3
671 end
672
673 test "renders empty array for the second page", %{conn: conn} do
674 insert(:user)
675
676 conn = get(conn, "/api/pleroma/admin/users?page=2")
677
678 assert json_response(conn, 200) == %{
679 "count" => 2,
680 "page_size" => 50,
681 "users" => []
682 }
683 end
684
685 test "regular search", %{conn: conn} do
686 user = insert(:user, nickname: "bob")
687
688 conn = get(conn, "/api/pleroma/admin/users?query=bo")
689
690 assert json_response(conn, 200) == %{
691 "count" => 1,
692 "page_size" => 50,
693 "users" => [
694 %{
695 "deactivated" => user.deactivated,
696 "id" => user.id,
697 "nickname" => user.nickname,
698 "roles" => %{"admin" => false, "moderator" => false},
699 "local" => true,
700 "tags" => [],
701 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
702 "display_name" => HTML.strip_tags(user.name || user.nickname),
703 "confirmation_pending" => false,
704 "url" => user.ap_id
705 }
706 ]
707 }
708 end
709
710 test "search by domain", %{conn: conn} do
711 user = insert(:user, nickname: "nickname@domain.com")
712 insert(:user)
713
714 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
715
716 assert json_response(conn, 200) == %{
717 "count" => 1,
718 "page_size" => 50,
719 "users" => [
720 %{
721 "deactivated" => user.deactivated,
722 "id" => user.id,
723 "nickname" => user.nickname,
724 "roles" => %{"admin" => false, "moderator" => false},
725 "local" => true,
726 "tags" => [],
727 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
728 "display_name" => HTML.strip_tags(user.name || user.nickname),
729 "confirmation_pending" => false,
730 "url" => user.ap_id
731 }
732 ]
733 }
734 end
735
736 test "search by full nickname", %{conn: conn} do
737 user = insert(:user, nickname: "nickname@domain.com")
738 insert(:user)
739
740 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
741
742 assert json_response(conn, 200) == %{
743 "count" => 1,
744 "page_size" => 50,
745 "users" => [
746 %{
747 "deactivated" => user.deactivated,
748 "id" => user.id,
749 "nickname" => user.nickname,
750 "roles" => %{"admin" => false, "moderator" => false},
751 "local" => true,
752 "tags" => [],
753 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
754 "display_name" => HTML.strip_tags(user.name || user.nickname),
755 "confirmation_pending" => false,
756 "url" => user.ap_id
757 }
758 ]
759 }
760 end
761
762 test "search by display name", %{conn: conn} do
763 user = insert(:user, name: "Display name")
764 insert(:user)
765
766 conn = get(conn, "/api/pleroma/admin/users?name=display")
767
768 assert json_response(conn, 200) == %{
769 "count" => 1,
770 "page_size" => 50,
771 "users" => [
772 %{
773 "deactivated" => user.deactivated,
774 "id" => user.id,
775 "nickname" => user.nickname,
776 "roles" => %{"admin" => false, "moderator" => false},
777 "local" => true,
778 "tags" => [],
779 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
780 "display_name" => HTML.strip_tags(user.name || user.nickname),
781 "confirmation_pending" => false,
782 "url" => user.ap_id
783 }
784 ]
785 }
786 end
787
788 test "search by email", %{conn: conn} do
789 user = insert(:user, email: "email@example.com")
790 insert(:user)
791
792 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
793
794 assert json_response(conn, 200) == %{
795 "count" => 1,
796 "page_size" => 50,
797 "users" => [
798 %{
799 "deactivated" => user.deactivated,
800 "id" => user.id,
801 "nickname" => user.nickname,
802 "roles" => %{"admin" => false, "moderator" => false},
803 "local" => true,
804 "tags" => [],
805 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
806 "display_name" => HTML.strip_tags(user.name || user.nickname),
807 "confirmation_pending" => false,
808 "url" => user.ap_id
809 }
810 ]
811 }
812 end
813
814 test "regular search with page size", %{conn: conn} do
815 user = insert(:user, nickname: "aalice")
816 user2 = insert(:user, nickname: "alice")
817
818 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
819
820 assert json_response(conn1, 200) == %{
821 "count" => 2,
822 "page_size" => 1,
823 "users" => [
824 %{
825 "deactivated" => user.deactivated,
826 "id" => user.id,
827 "nickname" => user.nickname,
828 "roles" => %{"admin" => false, "moderator" => false},
829 "local" => true,
830 "tags" => [],
831 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
832 "display_name" => HTML.strip_tags(user.name || user.nickname),
833 "confirmation_pending" => false,
834 "url" => user.ap_id
835 }
836 ]
837 }
838
839 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
840
841 assert json_response(conn2, 200) == %{
842 "count" => 2,
843 "page_size" => 1,
844 "users" => [
845 %{
846 "deactivated" => user2.deactivated,
847 "id" => user2.id,
848 "nickname" => user2.nickname,
849 "roles" => %{"admin" => false, "moderator" => false},
850 "local" => true,
851 "tags" => [],
852 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
853 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
854 "confirmation_pending" => false,
855 "url" => user2.ap_id
856 }
857 ]
858 }
859 end
860
861 test "only local users" do
862 admin = insert(:user, is_admin: true, nickname: "john")
863 token = insert(:oauth_admin_token, user: admin)
864 user = insert(:user, nickname: "bob")
865
866 insert(:user, nickname: "bobb", local: false)
867
868 conn =
869 build_conn()
870 |> assign(:user, admin)
871 |> assign(:token, token)
872 |> get("/api/pleroma/admin/users?query=bo&filters=local")
873
874 assert json_response(conn, 200) == %{
875 "count" => 1,
876 "page_size" => 50,
877 "users" => [
878 %{
879 "deactivated" => user.deactivated,
880 "id" => user.id,
881 "nickname" => user.nickname,
882 "roles" => %{"admin" => false, "moderator" => false},
883 "local" => true,
884 "tags" => [],
885 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
886 "display_name" => HTML.strip_tags(user.name || user.nickname),
887 "confirmation_pending" => false,
888 "url" => user.ap_id
889 }
890 ]
891 }
892 end
893
894 test "only local users with no query", %{conn: conn, admin: old_admin} do
895 admin = insert(:user, is_admin: true, nickname: "john")
896 user = insert(:user, nickname: "bob")
897
898 insert(:user, nickname: "bobb", local: false)
899
900 conn = get(conn, "/api/pleroma/admin/users?filters=local")
901
902 users =
903 [
904 %{
905 "deactivated" => user.deactivated,
906 "id" => user.id,
907 "nickname" => user.nickname,
908 "roles" => %{"admin" => false, "moderator" => false},
909 "local" => true,
910 "tags" => [],
911 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
912 "display_name" => HTML.strip_tags(user.name || user.nickname),
913 "confirmation_pending" => false,
914 "url" => user.ap_id
915 },
916 %{
917 "deactivated" => admin.deactivated,
918 "id" => admin.id,
919 "nickname" => admin.nickname,
920 "roles" => %{"admin" => true, "moderator" => false},
921 "local" => true,
922 "tags" => [],
923 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
924 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
925 "confirmation_pending" => false,
926 "url" => admin.ap_id
927 },
928 %{
929 "deactivated" => false,
930 "id" => old_admin.id,
931 "local" => true,
932 "nickname" => old_admin.nickname,
933 "roles" => %{"admin" => true, "moderator" => false},
934 "tags" => [],
935 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
936 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
937 "confirmation_pending" => false,
938 "url" => old_admin.ap_id
939 }
940 ]
941 |> Enum.sort_by(& &1["nickname"])
942
943 assert json_response(conn, 200) == %{
944 "count" => 3,
945 "page_size" => 50,
946 "users" => users
947 }
948 end
949
950 test "load only admins", %{conn: conn, admin: admin} do
951 second_admin = insert(:user, is_admin: true)
952 insert(:user)
953 insert(:user)
954
955 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
956
957 users =
958 [
959 %{
960 "deactivated" => false,
961 "id" => admin.id,
962 "nickname" => admin.nickname,
963 "roles" => %{"admin" => true, "moderator" => false},
964 "local" => admin.local,
965 "tags" => [],
966 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
967 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
968 "confirmation_pending" => false,
969 "url" => admin.ap_id
970 },
971 %{
972 "deactivated" => false,
973 "id" => second_admin.id,
974 "nickname" => second_admin.nickname,
975 "roles" => %{"admin" => true, "moderator" => false},
976 "local" => second_admin.local,
977 "tags" => [],
978 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
979 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
980 "confirmation_pending" => false,
981 "url" => second_admin.ap_id
982 }
983 ]
984 |> Enum.sort_by(& &1["nickname"])
985
986 assert json_response(conn, 200) == %{
987 "count" => 2,
988 "page_size" => 50,
989 "users" => users
990 }
991 end
992
993 test "load only moderators", %{conn: conn} do
994 moderator = insert(:user, is_moderator: true)
995 insert(:user)
996 insert(:user)
997
998 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
999
1000 assert json_response(conn, 200) == %{
1001 "count" => 1,
1002 "page_size" => 50,
1003 "users" => [
1004 %{
1005 "deactivated" => false,
1006 "id" => moderator.id,
1007 "nickname" => moderator.nickname,
1008 "roles" => %{"admin" => false, "moderator" => true},
1009 "local" => moderator.local,
1010 "tags" => [],
1011 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
1012 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
1013 "confirmation_pending" => false,
1014 "url" => moderator.ap_id
1015 }
1016 ]
1017 }
1018 end
1019
1020 test "load users with tags list", %{conn: conn} do
1021 user1 = insert(:user, tags: ["first"])
1022 user2 = insert(:user, tags: ["second"])
1023 insert(:user)
1024 insert(:user)
1025
1026 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
1027
1028 users =
1029 [
1030 %{
1031 "deactivated" => false,
1032 "id" => user1.id,
1033 "nickname" => user1.nickname,
1034 "roles" => %{"admin" => false, "moderator" => false},
1035 "local" => user1.local,
1036 "tags" => ["first"],
1037 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
1038 "display_name" => HTML.strip_tags(user1.name || user1.nickname),
1039 "confirmation_pending" => false,
1040 "url" => user1.ap_id
1041 },
1042 %{
1043 "deactivated" => false,
1044 "id" => user2.id,
1045 "nickname" => user2.nickname,
1046 "roles" => %{"admin" => false, "moderator" => false},
1047 "local" => user2.local,
1048 "tags" => ["second"],
1049 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1050 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
1051 "confirmation_pending" => false,
1052 "url" => user2.ap_id
1053 }
1054 ]
1055 |> Enum.sort_by(& &1["nickname"])
1056
1057 assert json_response(conn, 200) == %{
1058 "count" => 2,
1059 "page_size" => 50,
1060 "users" => users
1061 }
1062 end
1063
1064 test "it works with multiple filters" do
1065 admin = insert(:user, nickname: "john", is_admin: true)
1066 token = insert(:oauth_admin_token, user: admin)
1067 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1068
1069 insert(:user, nickname: "ken", local: true, deactivated: true)
1070 insert(:user, nickname: "bobb", local: false, deactivated: false)
1071
1072 conn =
1073 build_conn()
1074 |> assign(:user, admin)
1075 |> assign(:token, token)
1076 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1077
1078 assert json_response(conn, 200) == %{
1079 "count" => 1,
1080 "page_size" => 50,
1081 "users" => [
1082 %{
1083 "deactivated" => user.deactivated,
1084 "id" => user.id,
1085 "nickname" => user.nickname,
1086 "roles" => %{"admin" => false, "moderator" => false},
1087 "local" => user.local,
1088 "tags" => [],
1089 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1090 "display_name" => HTML.strip_tags(user.name || user.nickname),
1091 "confirmation_pending" => false,
1092 "url" => user.ap_id
1093 }
1094 ]
1095 }
1096 end
1097
1098 test "it omits relay user", %{admin: admin, conn: conn} do
1099 assert %User{} = Relay.get_actor()
1100
1101 conn = get(conn, "/api/pleroma/admin/users")
1102
1103 assert json_response(conn, 200) == %{
1104 "count" => 1,
1105 "page_size" => 50,
1106 "users" => [
1107 %{
1108 "deactivated" => admin.deactivated,
1109 "id" => admin.id,
1110 "nickname" => admin.nickname,
1111 "roles" => %{"admin" => true, "moderator" => false},
1112 "local" => true,
1113 "tags" => [],
1114 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1115 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
1116 "confirmation_pending" => false,
1117 "url" => admin.ap_id
1118 }
1119 ]
1120 }
1121 end
1122 end
1123
1124 test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
1125 user_one = insert(:user, deactivated: true)
1126 user_two = insert(:user, deactivated: true)
1127
1128 conn =
1129 patch(
1130 conn,
1131 "/api/pleroma/admin/users/activate",
1132 %{nicknames: [user_one.nickname, user_two.nickname]}
1133 )
1134
1135 response = json_response(conn, 200)
1136 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1137
1138 log_entry = Repo.one(ModerationLog)
1139
1140 assert ModerationLog.get_log_entry_message(log_entry) ==
1141 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1142 end
1143
1144 test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
1145 user_one = insert(:user, deactivated: false)
1146 user_two = insert(:user, deactivated: false)
1147
1148 conn =
1149 patch(
1150 conn,
1151 "/api/pleroma/admin/users/deactivate",
1152 %{nicknames: [user_one.nickname, user_two.nickname]}
1153 )
1154
1155 response = json_response(conn, 200)
1156 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1157
1158 log_entry = Repo.one(ModerationLog)
1159
1160 assert ModerationLog.get_log_entry_message(log_entry) ==
1161 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1162 end
1163
1164 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
1165 user = insert(:user)
1166
1167 conn = patch(conn, "/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1168
1169 assert json_response(conn, 200) ==
1170 %{
1171 "deactivated" => !user.deactivated,
1172 "id" => user.id,
1173 "nickname" => user.nickname,
1174 "roles" => %{"admin" => false, "moderator" => false},
1175 "local" => true,
1176 "tags" => [],
1177 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1178 "display_name" => HTML.strip_tags(user.name || user.nickname),
1179 "confirmation_pending" => false,
1180 "url" => user.ap_id
1181 }
1182
1183 log_entry = Repo.one(ModerationLog)
1184
1185 assert ModerationLog.get_log_entry_message(log_entry) ==
1186 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1187 end
1188
1189 describe "PUT disable_mfa" do
1190 test "returns 200 and disable 2fa", %{conn: conn} do
1191 user =
1192 insert(:user,
1193 multi_factor_authentication_settings: %MFA.Settings{
1194 enabled: true,
1195 totp: %MFA.Settings.TOTP{secret: "otp_secret", confirmed: true}
1196 }
1197 )
1198
1199 response =
1200 conn
1201 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: user.nickname})
1202 |> json_response(200)
1203
1204 assert response == user.nickname
1205 mfa_settings = refresh_record(user).multi_factor_authentication_settings
1206
1207 refute mfa_settings.enabled
1208 refute mfa_settings.totp.confirmed
1209 end
1210
1211 test "returns 404 if user not found", %{conn: conn} do
1212 response =
1213 conn
1214 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
1215 |> json_response(404)
1216
1217 assert response == %{"error" => "Not found"}
1218 end
1219 end
1220
1221 describe "GET /api/pleroma/admin/restart" do
1222 setup do: clear_config(:configurable_from_database, true)
1223
1224 test "pleroma restarts", %{conn: conn} do
1225 capture_log(fn ->
1226 assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
1227 end) =~ "pleroma restarted"
1228
1229 refute Restarter.Pleroma.need_reboot?()
1230 end
1231 end
1232
1233 test "need_reboot flag", %{conn: conn} do
1234 assert conn
1235 |> get("/api/pleroma/admin/need_reboot")
1236 |> json_response(200) == %{"need_reboot" => false}
1237
1238 Restarter.Pleroma.need_reboot()
1239
1240 assert conn
1241 |> get("/api/pleroma/admin/need_reboot")
1242 |> json_response(200) == %{"need_reboot" => true}
1243
1244 on_exit(fn -> Restarter.Pleroma.refresh() end)
1245 end
1246
1247 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
1248 setup do
1249 user = insert(:user)
1250
1251 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
1252 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
1253 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
1254
1255 insert(:note_activity, user: user, published: date1)
1256 insert(:note_activity, user: user, published: date2)
1257 insert(:note_activity, user: user, published: date3)
1258
1259 %{user: user}
1260 end
1261
1262 test "renders user's statuses", %{conn: conn, user: user} do
1263 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
1264
1265 assert json_response(conn, 200) |> length() == 3
1266 end
1267
1268 test "renders user's statuses with a limit", %{conn: conn, user: user} do
1269 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
1270
1271 assert json_response(conn, 200) |> length() == 2
1272 end
1273
1274 test "doesn't return private statuses by default", %{conn: conn, user: user} do
1275 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
1276
1277 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
1278
1279 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
1280
1281 assert json_response(conn, 200) |> length() == 4
1282 end
1283
1284 test "returns private statuses with godmode on", %{conn: conn, user: user} do
1285 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
1286
1287 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
1288
1289 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
1290
1291 assert json_response(conn, 200) |> length() == 5
1292 end
1293
1294 test "excludes reblogs by default", %{conn: conn, user: user} do
1295 other_user = insert(:user)
1296 {:ok, activity} = CommonAPI.post(user, %{status: "."})
1297 {:ok, %Activity{}} = CommonAPI.repeat(activity.id, other_user)
1298
1299 conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses")
1300 assert json_response(conn_res, 200) |> length() == 0
1301
1302 conn_res =
1303 get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true")
1304
1305 assert json_response(conn_res, 200) |> length() == 1
1306 end
1307 end
1308
1309 describe "GET /api/pleroma/admin/moderation_log" do
1310 setup do
1311 moderator = insert(:user, is_moderator: true)
1312
1313 %{moderator: moderator}
1314 end
1315
1316 test "returns the log", %{conn: conn, admin: admin} do
1317 Repo.insert(%ModerationLog{
1318 data: %{
1319 actor: %{
1320 "id" => admin.id,
1321 "nickname" => admin.nickname,
1322 "type" => "user"
1323 },
1324 action: "relay_follow",
1325 target: "https://example.org/relay"
1326 },
1327 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
1328 })
1329
1330 Repo.insert(%ModerationLog{
1331 data: %{
1332 actor: %{
1333 "id" => admin.id,
1334 "nickname" => admin.nickname,
1335 "type" => "user"
1336 },
1337 action: "relay_unfollow",
1338 target: "https://example.org/relay"
1339 },
1340 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
1341 })
1342
1343 conn = get(conn, "/api/pleroma/admin/moderation_log")
1344
1345 response = json_response(conn, 200)
1346 [first_entry, second_entry] = response["items"]
1347
1348 assert response["total"] == 2
1349 assert first_entry["data"]["action"] == "relay_unfollow"
1350
1351 assert first_entry["message"] ==
1352 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
1353
1354 assert second_entry["data"]["action"] == "relay_follow"
1355
1356 assert second_entry["message"] ==
1357 "@#{admin.nickname} followed relay: https://example.org/relay"
1358 end
1359
1360 test "returns the log with pagination", %{conn: conn, admin: admin} do
1361 Repo.insert(%ModerationLog{
1362 data: %{
1363 actor: %{
1364 "id" => admin.id,
1365 "nickname" => admin.nickname,
1366 "type" => "user"
1367 },
1368 action: "relay_follow",
1369 target: "https://example.org/relay"
1370 },
1371 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
1372 })
1373
1374 Repo.insert(%ModerationLog{
1375 data: %{
1376 actor: %{
1377 "id" => admin.id,
1378 "nickname" => admin.nickname,
1379 "type" => "user"
1380 },
1381 action: "relay_unfollow",
1382 target: "https://example.org/relay"
1383 },
1384 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
1385 })
1386
1387 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
1388
1389 response1 = json_response(conn1, 200)
1390 [first_entry] = response1["items"]
1391
1392 assert response1["total"] == 2
1393 assert response1["items"] |> length() == 1
1394 assert first_entry["data"]["action"] == "relay_unfollow"
1395
1396 assert first_entry["message"] ==
1397 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
1398
1399 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
1400
1401 response2 = json_response(conn2, 200)
1402 [second_entry] = response2["items"]
1403
1404 assert response2["total"] == 2
1405 assert response2["items"] |> length() == 1
1406 assert second_entry["data"]["action"] == "relay_follow"
1407
1408 assert second_entry["message"] ==
1409 "@#{admin.nickname} followed relay: https://example.org/relay"
1410 end
1411
1412 test "filters log by date", %{conn: conn, admin: admin} do
1413 first_date = "2017-08-15T15:47:06Z"
1414 second_date = "2017-08-20T15:47:06Z"
1415
1416 Repo.insert(%ModerationLog{
1417 data: %{
1418 actor: %{
1419 "id" => admin.id,
1420 "nickname" => admin.nickname,
1421 "type" => "user"
1422 },
1423 action: "relay_follow",
1424 target: "https://example.org/relay"
1425 },
1426 inserted_at: NaiveDateTime.from_iso8601!(first_date)
1427 })
1428
1429 Repo.insert(%ModerationLog{
1430 data: %{
1431 actor: %{
1432 "id" => admin.id,
1433 "nickname" => admin.nickname,
1434 "type" => "user"
1435 },
1436 action: "relay_unfollow",
1437 target: "https://example.org/relay"
1438 },
1439 inserted_at: NaiveDateTime.from_iso8601!(second_date)
1440 })
1441
1442 conn1 =
1443 get(
1444 conn,
1445 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
1446 )
1447
1448 response1 = json_response(conn1, 200)
1449 [first_entry] = response1["items"]
1450
1451 assert response1["total"] == 1
1452 assert first_entry["data"]["action"] == "relay_unfollow"
1453
1454 assert first_entry["message"] ==
1455 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
1456 end
1457
1458 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
1459 Repo.insert(%ModerationLog{
1460 data: %{
1461 actor: %{
1462 "id" => admin.id,
1463 "nickname" => admin.nickname,
1464 "type" => "user"
1465 },
1466 action: "relay_follow",
1467 target: "https://example.org/relay"
1468 }
1469 })
1470
1471 Repo.insert(%ModerationLog{
1472 data: %{
1473 actor: %{
1474 "id" => moderator.id,
1475 "nickname" => moderator.nickname,
1476 "type" => "user"
1477 },
1478 action: "relay_unfollow",
1479 target: "https://example.org/relay"
1480 }
1481 })
1482
1483 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
1484
1485 response1 = json_response(conn1, 200)
1486 [first_entry] = response1["items"]
1487
1488 assert response1["total"] == 1
1489 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
1490 end
1491
1492 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
1493 ModerationLog.insert_log(%{
1494 actor: moderator,
1495 action: "relay_follow",
1496 target: "https://example.org/relay"
1497 })
1498
1499 ModerationLog.insert_log(%{
1500 actor: moderator,
1501 action: "relay_unfollow",
1502 target: "https://example.org/relay"
1503 })
1504
1505 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
1506
1507 response1 = json_response(conn1, 200)
1508 [first_entry] = response1["items"]
1509
1510 assert response1["total"] == 1
1511
1512 assert get_in(first_entry, ["data", "message"]) ==
1513 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
1514 end
1515 end
1516
1517 test "gets a remote users when [:instance, :limit_to_local_content] is set to :unauthenticated",
1518 %{conn: conn} do
1519 clear_config(Pleroma.Config.get([:instance, :limit_to_local_content]), :unauthenticated)
1520 user = insert(:user, %{local: false, nickname: "u@peer1.com"})
1521 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
1522
1523 assert json_response(conn, 200)
1524 end
1525
1526 describe "GET /users/:nickname/credentials" do
1527 test "gets the user credentials", %{conn: conn} do
1528 user = insert(:user)
1529 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
1530
1531 response = assert json_response(conn, 200)
1532 assert response["email"] == user.email
1533 end
1534
1535 test "returns 403 if requested by a non-admin" do
1536 user = insert(:user)
1537
1538 conn =
1539 build_conn()
1540 |> assign(:user, user)
1541 |> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
1542
1543 assert json_response(conn, :forbidden)
1544 end
1545 end
1546
1547 describe "PATCH /users/:nickname/credentials" do
1548 setup do
1549 user = insert(:user)
1550 [user: user]
1551 end
1552
1553 test "changes password and email", %{conn: conn, admin: admin, user: user} do
1554 assert user.password_reset_pending == false
1555
1556 conn =
1557 patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
1558 "password" => "new_password",
1559 "email" => "new_email@example.com",
1560 "name" => "new_name"
1561 })
1562
1563 assert json_response(conn, 200) == %{"status" => "success"}
1564
1565 ObanHelpers.perform_all()
1566
1567 updated_user = User.get_by_id(user.id)
1568
1569 assert updated_user.email == "new_email@example.com"
1570 assert updated_user.name == "new_name"
1571 assert updated_user.password_hash != user.password_hash
1572 assert updated_user.password_reset_pending == true
1573
1574 [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
1575
1576 assert ModerationLog.get_log_entry_message(log_entry1) ==
1577 "@#{admin.nickname} updated users: @#{user.nickname}"
1578
1579 assert ModerationLog.get_log_entry_message(log_entry2) ==
1580 "@#{admin.nickname} forced password reset for users: @#{user.nickname}"
1581 end
1582
1583 test "returns 403 if requested by a non-admin", %{user: user} do
1584 conn =
1585 build_conn()
1586 |> assign(:user, user)
1587 |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
1588 "password" => "new_password",
1589 "email" => "new_email@example.com",
1590 "name" => "new_name"
1591 })
1592
1593 assert json_response(conn, :forbidden)
1594 end
1595
1596 test "changes actor type from permitted list", %{conn: conn, user: user} do
1597 assert user.actor_type == "Person"
1598
1599 assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
1600 "actor_type" => "Service"
1601 })
1602 |> json_response(200) == %{"status" => "success"}
1603
1604 updated_user = User.get_by_id(user.id)
1605
1606 assert updated_user.actor_type == "Service"
1607
1608 assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
1609 "actor_type" => "Application"
1610 })
1611 |> json_response(400) == %{"errors" => %{"actor_type" => "is invalid"}}
1612 end
1613
1614 test "update non existing user", %{conn: conn} do
1615 assert patch(conn, "/api/pleroma/admin/users/non-existing/credentials", %{
1616 "password" => "new_password"
1617 })
1618 |> json_response(404) == %{"error" => "Not found"}
1619 end
1620 end
1621
1622 describe "PATCH /users/:nickname/force_password_reset" do
1623 test "sets password_reset_pending to true", %{conn: conn} do
1624 user = insert(:user)
1625 assert user.password_reset_pending == false
1626
1627 conn =
1628 patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
1629
1630 assert json_response(conn, 204) == ""
1631
1632 ObanHelpers.perform_all()
1633
1634 assert User.get_by_id(user.id).password_reset_pending == true
1635 end
1636 end
1637
1638 describe "instances" do
1639 test "GET /instances/:instance/statuses", %{conn: conn} do
1640 user = insert(:user, local: false, nickname: "archaeme@archae.me")
1641 user2 = insert(:user, local: false, nickname: "test@test.com")
1642 insert_pair(:note_activity, user: user)
1643 activity = insert(:note_activity, user: user2)
1644
1645 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
1646
1647 response = json_response(ret_conn, 200)
1648
1649 assert length(response) == 2
1650
1651 ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses")
1652
1653 response = json_response(ret_conn, 200)
1654
1655 assert length(response) == 1
1656
1657 ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses")
1658
1659 response = json_response(ret_conn, 200)
1660
1661 assert Enum.empty?(response)
1662
1663 CommonAPI.repeat(activity.id, user)
1664
1665 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
1666 response = json_response(ret_conn, 200)
1667 assert length(response) == 2
1668
1669 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
1670 response = json_response(ret_conn, 200)
1671 assert length(response) == 3
1672 end
1673 end
1674
1675 describe "PATCH /confirm_email" do
1676 test "it confirms emails of two users", %{conn: conn, admin: admin} do
1677 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
1678
1679 assert first_user.confirmation_pending == true
1680 assert second_user.confirmation_pending == true
1681
1682 ret_conn =
1683 patch(conn, "/api/pleroma/admin/users/confirm_email", %{
1684 nicknames: [
1685 first_user.nickname,
1686 second_user.nickname
1687 ]
1688 })
1689
1690 assert ret_conn.status == 200
1691
1692 assert first_user.confirmation_pending == true
1693 assert second_user.confirmation_pending == true
1694
1695 log_entry = Repo.one(ModerationLog)
1696
1697 assert ModerationLog.get_log_entry_message(log_entry) ==
1698 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
1699 second_user.nickname
1700 }"
1701 end
1702 end
1703
1704 describe "PATCH /resend_confirmation_email" do
1705 test "it resend emails for two users", %{conn: conn, admin: admin} do
1706 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
1707
1708 ret_conn =
1709 patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{
1710 nicknames: [
1711 first_user.nickname,
1712 second_user.nickname
1713 ]
1714 })
1715
1716 assert ret_conn.status == 200
1717
1718 log_entry = Repo.one(ModerationLog)
1719
1720 assert ModerationLog.get_log_entry_message(log_entry) ==
1721 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
1722 second_user.nickname
1723 }"
1724 end
1725 end
1726
1727 describe "/api/pleroma/admin/stats" do
1728 test "status visibility count", %{conn: conn} do
1729 admin = insert(:user, is_admin: true)
1730 user = insert(:user)
1731 CommonAPI.post(user, %{visibility: "public", status: "hey"})
1732 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
1733 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
1734
1735 response =
1736 conn
1737 |> assign(:user, admin)
1738 |> get("/api/pleroma/admin/stats")
1739 |> json_response(200)
1740
1741 assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
1742 response["status_visibility"]
1743 end
1744
1745 test "by instance", %{conn: conn} do
1746 admin = insert(:user, is_admin: true)
1747 user1 = insert(:user)
1748 instance2 = "instance2.tld"
1749 user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
1750
1751 CommonAPI.post(user1, %{visibility: "public", status: "hey"})
1752 CommonAPI.post(user2, %{visibility: "unlisted", status: "hey"})
1753 CommonAPI.post(user2, %{visibility: "private", status: "hey"})
1754
1755 response =
1756 conn
1757 |> assign(:user, admin)
1758 |> get("/api/pleroma/admin/stats", instance: instance2)
1759 |> json_response(200)
1760
1761 assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
1762 response["status_visibility"]
1763 end
1764 end
1765 end
1766
1767 # Needed for testing
1768 defmodule Pleroma.Web.Endpoint.NotReal do
1769 end
1770
1771 defmodule Pleroma.Captcha.NotReal do
1772 end