1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
6 use Pleroma.Web.ConnCase
7 use Oban.Testing, repo: Pleroma.Repo
11 alias Pleroma.ModerationLog
13 alias Pleroma.ReportNote
14 alias Pleroma.Tests.ObanHelpers
16 alias Pleroma.UserInviteToken
17 alias Pleroma.Web.ActivityPub.Relay
18 alias Pleroma.Web.CommonAPI
19 alias Pleroma.Web.MediaProxy
20 import Pleroma.Factory
23 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
28 describe "DELETE /api/pleroma/admin/users" do
30 admin = insert(:user, is_admin: true)
35 |> assign(:user, admin)
36 |> put_req_header("accept", "application/json")
37 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
39 log_entry = Repo.one(ModerationLog)
41 assert ModerationLog.get_log_entry_message(log_entry) ==
42 "@#{admin.nickname} deleted users: @#{user.nickname}"
44 assert json_response(conn, 200) == user.nickname
47 test "multiple users" do
48 admin = insert(:user, is_admin: true)
49 user_one = insert(:user)
50 user_two = insert(:user)
54 |> assign(:user, admin)
55 |> put_req_header("accept", "application/json")
56 |> delete("/api/pleroma/admin/users", %{
57 nicknames: [user_one.nickname, user_two.nickname]
60 log_entry = Repo.one(ModerationLog)
62 assert ModerationLog.get_log_entry_message(log_entry) ==
63 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
65 response = json_response(conn, 200)
66 assert response -- [user_one.nickname, user_two.nickname] == []
70 describe "/api/pleroma/admin/users" do
72 admin = insert(:user, is_admin: true)
76 |> assign(:user, admin)
77 |> put_req_header("accept", "application/json")
78 |> post("/api/pleroma/admin/users", %{
82 "email" => "lain@example.org",
86 "nickname" => "lain2",
87 "email" => "lain2@example.org",
93 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
94 assert response == ["success", "success"]
96 log_entry = Repo.one(ModerationLog)
98 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
101 test "Cannot create user with exisiting email" do
102 admin = insert(:user, is_admin: true)
107 |> assign(:user, admin)
108 |> put_req_header("accept", "application/json")
109 |> post("/api/pleroma/admin/users", %{
112 "nickname" => "lain",
113 "email" => user.email,
119 assert json_response(conn, 409) == [
123 "email" => user.email,
126 "error" => "email has already been taken",
132 test "Cannot create user with exisiting nickname" do
133 admin = insert(:user, is_admin: true)
138 |> assign(:user, admin)
139 |> put_req_header("accept", "application/json")
140 |> post("/api/pleroma/admin/users", %{
143 "nickname" => user.nickname,
144 "email" => "someuser@plerama.social",
150 assert json_response(conn, 409) == [
154 "email" => "someuser@plerama.social",
155 "nickname" => user.nickname
157 "error" => "nickname has already been taken",
163 test "Multiple user creation works in transaction" do
164 admin = insert(:user, is_admin: true)
169 |> assign(:user, admin)
170 |> put_req_header("accept", "application/json")
171 |> post("/api/pleroma/admin/users", %{
174 "nickname" => "newuser",
175 "email" => "newuser@pleroma.social",
179 "nickname" => "lain",
180 "email" => user.email,
186 assert json_response(conn, 409) == [
190 "email" => user.email,
193 "error" => "email has already been taken",
199 "email" => "newuser@pleroma.social",
200 "nickname" => "newuser"
207 assert User.get_by_nickname("newuser") === nil
211 describe "/api/pleroma/admin/users/:nickname" do
212 test "Show", %{conn: conn} do
213 admin = insert(:user, is_admin: true)
218 |> assign(:user, admin)
219 |> get("/api/pleroma/admin/users/#{user.nickname}")
222 "deactivated" => false,
223 "id" => to_string(user.id),
225 "nickname" => user.nickname,
226 "roles" => %{"admin" => false, "moderator" => false},
228 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
229 "display_name" => HTML.strip_tags(user.name || user.nickname),
230 "confirmation_pending" => false
233 assert expected == json_response(conn, 200)
236 test "when the user doesn't exist", %{conn: conn} do
237 admin = insert(:user, is_admin: true)
242 |> assign(:user, admin)
243 |> get("/api/pleroma/admin/users/#{user.nickname}")
245 assert "Not found" == json_response(conn, 404)
249 describe "/api/pleroma/admin/users/follow" do
250 test "allows to force-follow another user" do
251 admin = insert(:user, is_admin: true)
253 follower = insert(:user)
256 |> assign(:user, admin)
257 |> put_req_header("accept", "application/json")
258 |> post("/api/pleroma/admin/users/follow", %{
259 "follower" => follower.nickname,
260 "followed" => user.nickname
263 user = User.get_cached_by_id(user.id)
264 follower = User.get_cached_by_id(follower.id)
266 assert User.following?(follower, user)
268 log_entry = Repo.one(ModerationLog)
270 assert ModerationLog.get_log_entry_message(log_entry) ==
271 "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
275 describe "/api/pleroma/admin/users/unfollow" do
276 test "allows to force-unfollow another user" do
277 admin = insert(:user, is_admin: true)
279 follower = insert(:user)
281 User.follow(follower, user)
284 |> assign(:user, admin)
285 |> put_req_header("accept", "application/json")
286 |> post("/api/pleroma/admin/users/unfollow", %{
287 "follower" => follower.nickname,
288 "followed" => user.nickname
291 user = User.get_cached_by_id(user.id)
292 follower = User.get_cached_by_id(follower.id)
294 refute User.following?(follower, user)
296 log_entry = Repo.one(ModerationLog)
298 assert ModerationLog.get_log_entry_message(log_entry) ==
299 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
303 describe "PUT /api/pleroma/admin/users/tag" do
305 admin = insert(:user, is_admin: true)
306 user1 = insert(:user, %{tags: ["x"]})
307 user2 = insert(:user, %{tags: ["y"]})
308 user3 = insert(:user, %{tags: ["unchanged"]})
312 |> assign(:user, admin)
313 |> put_req_header("accept", "application/json")
315 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
317 }&tags[]=foo&tags[]=bar"
320 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
323 test "it appends specified tags to users with specified nicknames", %{
329 assert json_response(conn, :no_content)
330 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
331 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
333 log_entry = Repo.one(ModerationLog)
336 [user1.nickname, user2.nickname]
337 |> Enum.map(&"@#{&1}")
340 tags = ["foo", "bar"] |> Enum.join(", ")
342 assert ModerationLog.get_log_entry_message(log_entry) ==
343 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
346 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
347 assert json_response(conn, :no_content)
348 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
352 describe "DELETE /api/pleroma/admin/users/tag" do
354 admin = insert(:user, is_admin: true)
355 user1 = insert(:user, %{tags: ["x"]})
356 user2 = insert(:user, %{tags: ["y", "z"]})
357 user3 = insert(:user, %{tags: ["unchanged"]})
361 |> assign(:user, admin)
362 |> put_req_header("accept", "application/json")
364 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
369 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
372 test "it removes specified tags from users with specified nicknames", %{
378 assert json_response(conn, :no_content)
379 assert User.get_cached_by_id(user1.id).tags == []
380 assert User.get_cached_by_id(user2.id).tags == ["y"]
382 log_entry = Repo.one(ModerationLog)
385 [user1.nickname, user2.nickname]
386 |> Enum.map(&"@#{&1}")
389 tags = ["x", "z"] |> Enum.join(", ")
391 assert ModerationLog.get_log_entry_message(log_entry) ==
392 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
395 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
396 assert json_response(conn, :no_content)
397 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
401 describe "/api/pleroma/admin/users/:nickname/permission_group" do
402 test "GET is giving user_info" do
403 admin = insert(:user, is_admin: true)
407 |> assign(:user, admin)
408 |> put_req_header("accept", "application/json")
409 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
411 assert json_response(conn, 200) == %{
413 "is_moderator" => false
417 test "/:right POST, can add to a permission group" do
418 admin = insert(:user, is_admin: true)
423 |> assign(:user, admin)
424 |> put_req_header("accept", "application/json")
425 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
427 assert json_response(conn, 200) == %{
431 log_entry = Repo.one(ModerationLog)
433 assert ModerationLog.get_log_entry_message(log_entry) ==
434 "@#{admin.nickname} made @#{user.nickname} admin"
437 test "/:right POST, can add to a permission group (multiple)" do
438 admin = insert(:user, is_admin: true)
439 user_one = insert(:user)
440 user_two = insert(:user)
444 |> assign(:user, admin)
445 |> put_req_header("accept", "application/json")
446 |> post("/api/pleroma/admin/users/permission_group/admin", %{
447 nicknames: [user_one.nickname, user_two.nickname]
450 assert json_response(conn, 200) == %{
454 log_entry = Repo.one(ModerationLog)
456 assert ModerationLog.get_log_entry_message(log_entry) ==
457 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
460 test "/:right DELETE, can remove from a permission group" do
461 admin = insert(:user, is_admin: true)
462 user = insert(:user, is_admin: true)
466 |> assign(:user, admin)
467 |> put_req_header("accept", "application/json")
468 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
470 assert json_response(conn, 200) == %{
474 log_entry = Repo.one(ModerationLog)
476 assert ModerationLog.get_log_entry_message(log_entry) ==
477 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
480 test "/:right DELETE, can remove from a permission group (multiple)" do
481 admin = insert(:user, is_admin: true)
482 user_one = insert(:user, is_admin: true)
483 user_two = insert(:user, is_admin: true)
487 |> assign(:user, admin)
488 |> put_req_header("accept", "application/json")
489 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
490 nicknames: [user_one.nickname, user_two.nickname]
493 assert json_response(conn, 200) == %{
497 log_entry = Repo.one(ModerationLog)
499 assert ModerationLog.get_log_entry_message(log_entry) ==
500 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
506 describe "POST /api/pleroma/admin/email_invite, with valid config" do
508 [user: insert(:user, is_admin: true)]
511 clear_config([:instance, :registrations_open]) do
512 Pleroma.Config.put([:instance, :registrations_open], false)
515 clear_config([:instance, :invites_enabled]) do
516 Pleroma.Config.put([:instance, :invites_enabled], true)
519 test "sends invitation and returns 204", %{conn: conn, user: user} do
520 recipient_email = "foo@bar.com"
521 recipient_name = "J. D."
525 |> assign(:user, user)
527 "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
530 assert json_response(conn, :no_content)
532 token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken))
534 refute token_record.used
536 notify_email = Pleroma.Config.get([:instance, :notify_email])
537 instance_name = Pleroma.Config.get([:instance, :name])
540 Pleroma.Emails.UserEmail.user_invitation_email(
547 Swoosh.TestAssertions.assert_email_sent(
548 from: {instance_name, notify_email},
549 to: {recipient_name, recipient_email},
550 html_body: email.html_body
554 test "it returns 403 if requested by a non-admin", %{conn: conn} do
555 non_admin_user = insert(:user)
559 |> assign(:user, non_admin_user)
560 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
562 assert json_response(conn, :forbidden)
566 describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
568 [user: insert(:user, is_admin: true)]
571 clear_config([:instance, :registrations_open])
572 clear_config([:instance, :invites_enabled])
574 test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
575 Pleroma.Config.put([:instance, :registrations_open], false)
576 Pleroma.Config.put([:instance, :invites_enabled], false)
580 |> assign(:user, user)
581 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
583 assert json_response(conn, :internal_server_error)
586 test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
587 Pleroma.Config.put([:instance, :registrations_open], true)
588 Pleroma.Config.put([:instance, :invites_enabled], true)
592 |> assign(:user, user)
593 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
595 assert json_response(conn, :internal_server_error)
599 test "/api/pleroma/admin/users/:nickname/password_reset" do
600 admin = insert(:user, is_admin: true)
605 |> assign(:user, admin)
606 |> put_req_header("accept", "application/json")
607 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
609 resp = json_response(conn, 200)
611 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
614 describe "GET /api/pleroma/admin/users" do
616 admin = insert(:user, is_admin: true)
620 |> assign(:user, admin)
622 {:ok, conn: conn, admin: admin}
625 test "renders users array for the first page", %{conn: conn, admin: admin} do
626 user = insert(:user, local: false, tags: ["foo", "bar"])
627 conn = get(conn, "/api/pleroma/admin/users?page=1")
632 "deactivated" => admin.deactivated,
634 "nickname" => admin.nickname,
635 "roles" => %{"admin" => true, "moderator" => false},
638 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
639 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
640 "confirmation_pending" => false
643 "deactivated" => user.deactivated,
645 "nickname" => user.nickname,
646 "roles" => %{"admin" => false, "moderator" => false},
648 "tags" => ["foo", "bar"],
649 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
650 "display_name" => HTML.strip_tags(user.name || user.nickname),
651 "confirmation_pending" => false
654 |> Enum.sort_by(& &1["nickname"])
656 assert json_response(conn, 200) == %{
663 test "renders empty array for the second page", %{conn: conn} do
666 conn = get(conn, "/api/pleroma/admin/users?page=2")
668 assert json_response(conn, 200) == %{
675 test "regular search", %{conn: conn} do
676 user = insert(:user, nickname: "bob")
678 conn = get(conn, "/api/pleroma/admin/users?query=bo")
680 assert json_response(conn, 200) == %{
685 "deactivated" => user.deactivated,
687 "nickname" => user.nickname,
688 "roles" => %{"admin" => false, "moderator" => false},
691 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
692 "display_name" => HTML.strip_tags(user.name || user.nickname),
693 "confirmation_pending" => false
699 test "search by domain", %{conn: conn} do
700 user = insert(:user, nickname: "nickname@domain.com")
703 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
705 assert json_response(conn, 200) == %{
710 "deactivated" => user.deactivated,
712 "nickname" => user.nickname,
713 "roles" => %{"admin" => false, "moderator" => false},
716 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
717 "display_name" => HTML.strip_tags(user.name || user.nickname),
718 "confirmation_pending" => false
724 test "search by full nickname", %{conn: conn} do
725 user = insert(:user, nickname: "nickname@domain.com")
728 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
730 assert json_response(conn, 200) == %{
735 "deactivated" => user.deactivated,
737 "nickname" => user.nickname,
738 "roles" => %{"admin" => false, "moderator" => false},
741 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
742 "display_name" => HTML.strip_tags(user.name || user.nickname),
743 "confirmation_pending" => false
749 test "search by display name", %{conn: conn} do
750 user = insert(:user, name: "Display name")
753 conn = get(conn, "/api/pleroma/admin/users?name=display")
755 assert json_response(conn, 200) == %{
760 "deactivated" => user.deactivated,
762 "nickname" => user.nickname,
763 "roles" => %{"admin" => false, "moderator" => false},
766 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
767 "display_name" => HTML.strip_tags(user.name || user.nickname),
768 "confirmation_pending" => false
774 test "search by email", %{conn: conn} do
775 user = insert(:user, email: "email@example.com")
778 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
780 assert json_response(conn, 200) == %{
785 "deactivated" => user.deactivated,
787 "nickname" => user.nickname,
788 "roles" => %{"admin" => false, "moderator" => false},
791 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
792 "display_name" => HTML.strip_tags(user.name || user.nickname),
793 "confirmation_pending" => false
799 test "regular search with page size", %{conn: conn} do
800 user = insert(:user, nickname: "aalice")
801 user2 = insert(:user, nickname: "alice")
803 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
805 assert json_response(conn1, 200) == %{
810 "deactivated" => user.deactivated,
812 "nickname" => user.nickname,
813 "roles" => %{"admin" => false, "moderator" => false},
816 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
817 "display_name" => HTML.strip_tags(user.name || user.nickname),
818 "confirmation_pending" => false
823 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
825 assert json_response(conn2, 200) == %{
830 "deactivated" => user2.deactivated,
832 "nickname" => user2.nickname,
833 "roles" => %{"admin" => false, "moderator" => false},
836 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
837 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
838 "confirmation_pending" => false
844 test "only local users" do
845 admin = insert(:user, is_admin: true, nickname: "john")
846 user = insert(:user, nickname: "bob")
848 insert(:user, nickname: "bobb", local: false)
852 |> assign(:user, admin)
853 |> get("/api/pleroma/admin/users?query=bo&filters=local")
855 assert json_response(conn, 200) == %{
860 "deactivated" => user.deactivated,
862 "nickname" => user.nickname,
863 "roles" => %{"admin" => false, "moderator" => false},
866 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
867 "display_name" => HTML.strip_tags(user.name || user.nickname),
868 "confirmation_pending" => false
874 test "only local users with no query", %{admin: old_admin} do
875 admin = insert(:user, is_admin: true, nickname: "john")
876 user = insert(:user, nickname: "bob")
878 insert(:user, nickname: "bobb", local: false)
882 |> assign(:user, admin)
883 |> get("/api/pleroma/admin/users?filters=local")
888 "deactivated" => user.deactivated,
890 "nickname" => user.nickname,
891 "roles" => %{"admin" => false, "moderator" => false},
894 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
895 "display_name" => HTML.strip_tags(user.name || user.nickname),
896 "confirmation_pending" => false
899 "deactivated" => admin.deactivated,
901 "nickname" => admin.nickname,
902 "roles" => %{"admin" => true, "moderator" => false},
905 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
906 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
907 "confirmation_pending" => false
910 "deactivated" => false,
911 "id" => old_admin.id,
913 "nickname" => old_admin.nickname,
914 "roles" => %{"admin" => true, "moderator" => false},
916 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
917 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
918 "confirmation_pending" => false
921 |> Enum.sort_by(& &1["nickname"])
923 assert json_response(conn, 200) == %{
930 test "load only admins", %{conn: conn, admin: admin} do
931 second_admin = insert(:user, is_admin: true)
935 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
940 "deactivated" => false,
942 "nickname" => admin.nickname,
943 "roles" => %{"admin" => true, "moderator" => false},
944 "local" => admin.local,
946 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
947 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
948 "confirmation_pending" => false
951 "deactivated" => false,
952 "id" => second_admin.id,
953 "nickname" => second_admin.nickname,
954 "roles" => %{"admin" => true, "moderator" => false},
955 "local" => second_admin.local,
957 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
958 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
959 "confirmation_pending" => false
962 |> Enum.sort_by(& &1["nickname"])
964 assert json_response(conn, 200) == %{
971 test "load only moderators", %{conn: conn} do
972 moderator = insert(:user, is_moderator: true)
976 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
978 assert json_response(conn, 200) == %{
983 "deactivated" => false,
984 "id" => moderator.id,
985 "nickname" => moderator.nickname,
986 "roles" => %{"admin" => false, "moderator" => true},
987 "local" => moderator.local,
989 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
990 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
991 "confirmation_pending" => false
997 test "load users with tags list", %{conn: conn} do
998 user1 = insert(:user, tags: ["first"])
999 user2 = insert(:user, tags: ["second"])
1003 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
1008 "deactivated" => false,
1010 "nickname" => user1.nickname,
1011 "roles" => %{"admin" => false, "moderator" => false},
1012 "local" => user1.local,
1013 "tags" => ["first"],
1014 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
1015 "display_name" => HTML.strip_tags(user1.name || user1.nickname),
1016 "confirmation_pending" => false
1019 "deactivated" => false,
1021 "nickname" => user2.nickname,
1022 "roles" => %{"admin" => false, "moderator" => false},
1023 "local" => user2.local,
1024 "tags" => ["second"],
1025 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1026 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
1027 "confirmation_pending" => false
1030 |> Enum.sort_by(& &1["nickname"])
1032 assert json_response(conn, 200) == %{
1039 test "it works with multiple filters" do
1040 admin = insert(:user, nickname: "john", is_admin: true)
1041 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1043 insert(:user, nickname: "ken", local: true, deactivated: true)
1044 insert(:user, nickname: "bobb", local: false, deactivated: false)
1048 |> assign(:user, admin)
1049 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1051 assert json_response(conn, 200) == %{
1056 "deactivated" => user.deactivated,
1058 "nickname" => user.nickname,
1059 "roles" => %{"admin" => false, "moderator" => false},
1060 "local" => user.local,
1062 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1063 "display_name" => HTML.strip_tags(user.name || user.nickname),
1064 "confirmation_pending" => false
1070 test "it omits relay user", %{admin: admin} do
1071 assert %User{} = Relay.get_actor()
1075 |> assign(:user, admin)
1076 |> get("/api/pleroma/admin/users")
1078 assert json_response(conn, 200) == %{
1083 "deactivated" => admin.deactivated,
1085 "nickname" => admin.nickname,
1086 "roles" => %{"admin" => true, "moderator" => false},
1089 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1090 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
1091 "confirmation_pending" => false
1098 test "PATCH /api/pleroma/admin/users/activate" do
1099 admin = insert(:user, is_admin: true)
1100 user_one = insert(:user, deactivated: true)
1101 user_two = insert(:user, deactivated: true)
1105 |> assign(:user, admin)
1107 "/api/pleroma/admin/users/activate",
1108 %{nicknames: [user_one.nickname, user_two.nickname]}
1111 response = json_response(conn, 200)
1112 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1114 log_entry = Repo.one(ModerationLog)
1116 assert ModerationLog.get_log_entry_message(log_entry) ==
1117 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1120 test "PATCH /api/pleroma/admin/users/deactivate" do
1121 admin = insert(:user, is_admin: true)
1122 user_one = insert(:user, deactivated: false)
1123 user_two = insert(:user, deactivated: false)
1127 |> assign(:user, admin)
1129 "/api/pleroma/admin/users/deactivate",
1130 %{nicknames: [user_one.nickname, user_two.nickname]}
1133 response = json_response(conn, 200)
1134 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1136 log_entry = Repo.one(ModerationLog)
1138 assert ModerationLog.get_log_entry_message(log_entry) ==
1139 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1142 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
1143 admin = insert(:user, is_admin: true)
1144 user = insert(:user)
1148 |> assign(:user, admin)
1149 |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1151 assert json_response(conn, 200) ==
1153 "deactivated" => !user.deactivated,
1155 "nickname" => user.nickname,
1156 "roles" => %{"admin" => false, "moderator" => false},
1159 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1160 "display_name" => HTML.strip_tags(user.name || user.nickname),
1161 "confirmation_pending" => false
1164 log_entry = Repo.one(ModerationLog)
1166 assert ModerationLog.get_log_entry_message(log_entry) ==
1167 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1170 describe "POST /api/pleroma/admin/users/invite_token" do
1172 admin = insert(:user, is_admin: true)
1176 |> assign(:user, admin)
1181 test "without options", %{conn: conn} do
1182 conn = post(conn, "/api/pleroma/admin/users/invite_token")
1184 invite_json = json_response(conn, 200)
1185 invite = UserInviteToken.find_by_token!(invite_json["token"])
1187 refute invite.expires_at
1188 refute invite.max_use
1189 assert invite.invite_type == "one_time"
1192 test "with expires_at", %{conn: conn} do
1194 post(conn, "/api/pleroma/admin/users/invite_token", %{
1195 "expires_at" => Date.to_string(Date.utc_today())
1198 invite_json = json_response(conn, 200)
1199 invite = UserInviteToken.find_by_token!(invite_json["token"])
1202 assert invite.expires_at == Date.utc_today()
1203 refute invite.max_use
1204 assert invite.invite_type == "date_limited"
1207 test "with max_use", %{conn: conn} do
1208 conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
1210 invite_json = json_response(conn, 200)
1211 invite = UserInviteToken.find_by_token!(invite_json["token"])
1213 refute invite.expires_at
1214 assert invite.max_use == 150
1215 assert invite.invite_type == "reusable"
1218 test "with max use and expires_at", %{conn: conn} do
1220 post(conn, "/api/pleroma/admin/users/invite_token", %{
1222 "expires_at" => Date.to_string(Date.utc_today())
1225 invite_json = json_response(conn, 200)
1226 invite = UserInviteToken.find_by_token!(invite_json["token"])
1228 assert invite.expires_at == Date.utc_today()
1229 assert invite.max_use == 150
1230 assert invite.invite_type == "reusable_date_limited"
1234 describe "GET /api/pleroma/admin/users/invites" do
1236 admin = insert(:user, is_admin: true)
1240 |> assign(:user, admin)
1245 test "no invites", %{conn: conn} do
1246 conn = get(conn, "/api/pleroma/admin/users/invites")
1248 assert json_response(conn, 200) == %{"invites" => []}
1251 test "with invite", %{conn: conn} do
1252 {:ok, invite} = UserInviteToken.create_invite()
1254 conn = get(conn, "/api/pleroma/admin/users/invites")
1256 assert json_response(conn, 200) == %{
1259 "expires_at" => nil,
1261 "invite_type" => "one_time",
1263 "token" => invite.token,
1272 describe "POST /api/pleroma/admin/users/revoke_invite" do
1273 test "with token" do
1274 admin = insert(:user, is_admin: true)
1275 {:ok, invite} = UserInviteToken.create_invite()
1279 |> assign(:user, admin)
1280 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
1282 assert json_response(conn, 200) == %{
1283 "expires_at" => nil,
1285 "invite_type" => "one_time",
1287 "token" => invite.token,
1293 test "with invalid token" do
1294 admin = insert(:user, is_admin: true)
1298 |> assign(:user, admin)
1299 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
1301 assert json_response(conn, :not_found) == "Not found"
1305 describe "GET /api/pleroma/admin/reports/:id" do
1306 setup %{conn: conn} do
1307 admin = insert(:user, is_admin: true)
1309 %{conn: assign(conn, :user, admin)}
1312 test "returns report by its id", %{conn: conn} do
1313 [reporter, target_user] = insert_pair(:user)
1314 activity = insert(:note_activity, user: target_user)
1316 {:ok, %{id: report_id}} =
1317 CommonAPI.report(reporter, %{
1318 "account_id" => target_user.id,
1319 "comment" => "I feel offended",
1320 "status_ids" => [activity.id]
1325 |> get("/api/pleroma/admin/reports/#{report_id}")
1326 |> json_response(:ok)
1328 assert response["id"] == report_id
1331 test "returns 404 when report id is invalid", %{conn: conn} do
1332 conn = get(conn, "/api/pleroma/admin/reports/test")
1334 assert json_response(conn, :not_found) == "Not found"
1338 describe "PATCH /api/pleroma/admin/reports" do
1339 setup %{conn: conn} do
1340 admin = insert(:user, is_admin: true)
1341 [reporter, target_user] = insert_pair(:user)
1342 activity = insert(:note_activity, user: target_user)
1344 {:ok, %{id: report_id}} =
1345 CommonAPI.report(reporter, %{
1346 "account_id" => target_user.id,
1347 "comment" => "I feel offended",
1348 "status_ids" => [activity.id]
1351 {:ok, %{id: second_report_id}} =
1352 CommonAPI.report(reporter, %{
1353 "account_id" => target_user.id,
1354 "comment" => "I feel very offended",
1355 "status_ids" => [activity.id]
1359 conn: assign(conn, :user, admin),
1362 second_report_id: second_report_id
1366 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1368 |> patch("/api/pleroma/admin/reports", %{
1370 %{"state" => "resolved", "id" => id}
1373 |> json_response(:no_content)
1375 activity = Activity.get_by_id(id)
1376 assert activity.data["state"] == "resolved"
1378 log_entry = Repo.one(ModerationLog)
1380 assert ModerationLog.get_log_entry_message(log_entry) ==
1381 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1384 test "closes report", %{conn: conn, id: id, admin: admin} do
1386 |> patch("/api/pleroma/admin/reports", %{
1388 %{"state" => "closed", "id" => id}
1391 |> json_response(:no_content)
1393 activity = Activity.get_by_id(id)
1394 assert activity.data["state"] == "closed"
1396 log_entry = Repo.one(ModerationLog)
1398 assert ModerationLog.get_log_entry_message(log_entry) ==
1399 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1402 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1405 |> patch("/api/pleroma/admin/reports", %{
1407 %{"state" => "test", "id" => id}
1411 assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
1414 test "returns 404 when report is not exist", %{conn: conn} do
1417 |> patch("/api/pleroma/admin/reports", %{
1419 %{"state" => "closed", "id" => "test"}
1423 assert hd(json_response(conn, :bad_request))["error"] == "not_found"
1426 test "updates state of multiple reports", %{
1430 second_report_id: second_report_id
1433 |> patch("/api/pleroma/admin/reports", %{
1435 %{"state" => "resolved", "id" => id},
1436 %{"state" => "closed", "id" => second_report_id}
1439 |> json_response(:no_content)
1441 activity = Activity.get_by_id(id)
1442 second_activity = Activity.get_by_id(second_report_id)
1443 assert activity.data["state"] == "resolved"
1444 assert second_activity.data["state"] == "closed"
1446 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
1448 assert ModerationLog.get_log_entry_message(first_log_entry) ==
1449 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1451 assert ModerationLog.get_log_entry_message(second_log_entry) ==
1452 "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
1456 describe "GET /api/pleroma/admin/reports" do
1457 setup %{conn: conn} do
1458 admin = insert(:user, is_admin: true)
1460 %{conn: assign(conn, :user, admin)}
1463 test "returns empty response when no reports created", %{conn: conn} do
1466 |> get("/api/pleroma/admin/reports")
1467 |> json_response(:ok)
1469 assert Enum.empty?(response["reports"])
1470 assert response["total"] == 0
1473 test "returns reports", %{conn: conn} do
1474 [reporter, target_user] = insert_pair(:user)
1475 activity = insert(:note_activity, user: target_user)
1477 {:ok, %{id: report_id}} =
1478 CommonAPI.report(reporter, %{
1479 "account_id" => target_user.id,
1480 "comment" => "I feel offended",
1481 "status_ids" => [activity.id]
1486 |> get("/api/pleroma/admin/reports")
1487 |> json_response(:ok)
1489 [report] = response["reports"]
1491 assert length(response["reports"]) == 1
1492 assert report["id"] == report_id
1494 assert response["total"] == 1
1497 test "returns reports with specified state", %{conn: conn} do
1498 [reporter, target_user] = insert_pair(:user)
1499 activity = insert(:note_activity, user: target_user)
1501 {:ok, %{id: first_report_id}} =
1502 CommonAPI.report(reporter, %{
1503 "account_id" => target_user.id,
1504 "comment" => "I feel offended",
1505 "status_ids" => [activity.id]
1508 {:ok, %{id: second_report_id}} =
1509 CommonAPI.report(reporter, %{
1510 "account_id" => target_user.id,
1511 "comment" => "I don't like this user"
1514 CommonAPI.update_report_state(second_report_id, "closed")
1518 |> get("/api/pleroma/admin/reports", %{
1521 |> json_response(:ok)
1523 [open_report] = response["reports"]
1525 assert length(response["reports"]) == 1
1526 assert open_report["id"] == first_report_id
1528 assert response["total"] == 1
1532 |> get("/api/pleroma/admin/reports", %{
1535 |> json_response(:ok)
1537 [closed_report] = response["reports"]
1539 assert length(response["reports"]) == 1
1540 assert closed_report["id"] == second_report_id
1542 assert response["total"] == 1
1546 |> get("/api/pleroma/admin/reports", %{
1547 "state" => "resolved"
1549 |> json_response(:ok)
1551 assert Enum.empty?(response["reports"])
1552 assert response["total"] == 0
1555 test "returns 403 when requested by a non-admin" do
1556 user = insert(:user)
1560 |> assign(:user, user)
1561 |> get("/api/pleroma/admin/reports")
1563 assert json_response(conn, :forbidden) == %{"error" => "User is not admin."}
1566 test "returns 403 when requested by anonymous" do
1569 |> get("/api/pleroma/admin/reports")
1571 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1575 describe "GET /api/pleroma/admin/grouped_reports" do
1576 setup %{conn: conn} do
1577 admin = insert(:user, is_admin: true)
1578 [reporter, target_user] = insert_pair(:user)
1580 date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
1581 date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
1582 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
1585 insert(:note_activity, user: target_user, data_attrs: %{"published" => date1})
1588 insert(:note_activity, user: target_user, data_attrs: %{"published" => date2})
1591 insert(:note_activity, user: target_user, data_attrs: %{"published" => date3})
1593 {:ok, first_report} =
1594 CommonAPI.report(reporter, %{
1595 "account_id" => target_user.id,
1596 "status_ids" => [first_status.id, second_status.id, third_status.id]
1599 {:ok, second_report} =
1600 CommonAPI.report(reporter, %{
1601 "account_id" => target_user.id,
1602 "status_ids" => [first_status.id, second_status.id]
1605 {:ok, third_report} =
1606 CommonAPI.report(reporter, %{
1607 "account_id" => target_user.id,
1608 "status_ids" => [first_status.id]
1612 conn: assign(conn, :user, admin),
1613 first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
1614 second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
1615 third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
1616 first_status_reports: [first_report, second_report, third_report],
1617 second_status_reports: [first_report, second_report],
1618 third_status_reports: [first_report],
1619 target_user: target_user,
1624 test "returns reports grouped by status", %{
1626 first_status: first_status,
1627 second_status: second_status,
1628 third_status: third_status,
1629 first_status_reports: first_status_reports,
1630 second_status_reports: second_status_reports,
1631 third_status_reports: third_status_reports,
1632 target_user: target_user,
1637 |> get("/api/pleroma/admin/grouped_reports")
1638 |> json_response(:ok)
1640 assert length(response["reports"]) == 3
1643 Enum.find(response["reports"], &(&1["status"]["id"] == first_status.data["id"]))
1646 Enum.find(response["reports"], &(&1["status"]["id"] == second_status.data["id"]))
1649 Enum.find(response["reports"], &(&1["status"]["id"] == third_status.data["id"]))
1651 assert length(first_group["reports"]) == 3
1652 assert length(second_group["reports"]) == 2
1653 assert length(third_group["reports"]) == 1
1655 assert first_group["date"] ==
1656 Enum.max_by(first_status_reports, fn act ->
1657 NaiveDateTime.from_iso8601!(act.data["published"])
1658 end).data["published"]
1660 assert first_group["status"] == %{
1661 "id" => first_status.data["id"],
1662 "content" => first_status.object.data["content"],
1663 "published" => first_status.object.data["published"]
1666 assert first_group["account"]["id"] == target_user.id
1668 assert length(first_group["actors"]) == 1
1669 assert hd(first_group["actors"])["id"] == reporter.id
1671 assert Enum.map(first_group["reports"], & &1["id"]) --
1672 Enum.map(first_status_reports, & &1.id) == []
1674 assert second_group["date"] ==
1675 Enum.max_by(second_status_reports, fn act ->
1676 NaiveDateTime.from_iso8601!(act.data["published"])
1677 end).data["published"]
1679 assert second_group["status"] == %{
1680 "id" => second_status.data["id"],
1681 "content" => second_status.object.data["content"],
1682 "published" => second_status.object.data["published"]
1685 assert second_group["account"]["id"] == target_user.id
1687 assert length(second_group["actors"]) == 1
1688 assert hd(second_group["actors"])["id"] == reporter.id
1690 assert Enum.map(second_group["reports"], & &1["id"]) --
1691 Enum.map(second_status_reports, & &1.id) == []
1693 assert third_group["date"] ==
1694 Enum.max_by(third_status_reports, fn act ->
1695 NaiveDateTime.from_iso8601!(act.data["published"])
1696 end).data["published"]
1698 assert third_group["status"] == %{
1699 "id" => third_status.data["id"],
1700 "content" => third_status.object.data["content"],
1701 "published" => third_status.object.data["published"]
1704 assert third_group["account"]["id"] == target_user.id
1706 assert length(third_group["actors"]) == 1
1707 assert hd(third_group["actors"])["id"] == reporter.id
1709 assert Enum.map(third_group["reports"], & &1["id"]) --
1710 Enum.map(third_status_reports, & &1.id) == []
1714 describe "PUT /api/pleroma/admin/statuses/:id" do
1715 setup %{conn: conn} do
1716 admin = insert(:user, is_admin: true)
1717 activity = insert(:note_activity)
1719 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1722 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1725 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1726 |> json_response(:ok)
1728 assert response["sensitive"]
1730 log_entry = Repo.one(ModerationLog)
1732 assert ModerationLog.get_log_entry_message(log_entry) ==
1733 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1737 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1738 |> json_response(:ok)
1740 refute response["sensitive"]
1743 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1746 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1747 |> json_response(:ok)
1749 assert response["visibility"] == "public"
1751 log_entry = Repo.one(ModerationLog)
1753 assert ModerationLog.get_log_entry_message(log_entry) ==
1754 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1758 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1759 |> json_response(:ok)
1761 assert response["visibility"] == "private"
1765 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1766 |> json_response(:ok)
1768 assert response["visibility"] == "unlisted"
1771 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1774 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1776 assert json_response(conn, :bad_request) == "Unsupported visibility"
1780 describe "DELETE /api/pleroma/admin/statuses/:id" do
1781 setup %{conn: conn} do
1782 admin = insert(:user, is_admin: true)
1783 activity = insert(:note_activity)
1785 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1788 test "deletes status", %{conn: conn, id: id, admin: admin} do
1790 |> delete("/api/pleroma/admin/statuses/#{id}")
1791 |> json_response(:ok)
1793 refute Activity.get_by_id(id)
1795 log_entry = Repo.one(ModerationLog)
1797 assert ModerationLog.get_log_entry_message(log_entry) ==
1798 "@#{admin.nickname} deleted status ##{id}"
1801 test "returns error when status is not exist", %{conn: conn} do
1804 |> delete("/api/pleroma/admin/statuses/test")
1806 assert json_response(conn, :bad_request) == "Could not delete"
1810 describe "GET /api/pleroma/admin/config" do
1811 setup %{conn: conn} do
1812 admin = insert(:user, is_admin: true)
1814 %{conn: assign(conn, :user, admin)}
1817 test "without any settings in db", %{conn: conn} do
1818 conn = get(conn, "/api/pleroma/admin/config")
1820 assert json_response(conn, 200) == %{"configs" => []}
1823 test "with settings in db", %{conn: conn} do
1824 config1 = insert(:config)
1825 config2 = insert(:config)
1827 conn = get(conn, "/api/pleroma/admin/config")
1840 } = json_response(conn, 200)
1842 assert key1 == config1.key
1843 assert key2 == config2.key
1847 describe "POST /api/pleroma/admin/config" do
1848 setup %{conn: conn} do
1849 admin = insert(:user, is_admin: true)
1851 temp_file = "config/test.exported_from_db.secret.exs"
1854 Application.delete_env(:pleroma, :key1)
1855 Application.delete_env(:pleroma, :key2)
1856 Application.delete_env(:pleroma, :key3)
1857 Application.delete_env(:pleroma, :key4)
1858 Application.delete_env(:pleroma, :keyaa1)
1859 Application.delete_env(:pleroma, :keyaa2)
1860 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1861 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1862 :ok = File.rm(temp_file)
1865 %{conn: assign(conn, :user, admin)}
1868 clear_config([:instance, :dynamic_configuration]) do
1869 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1872 @tag capture_log: true
1873 test "create new config setting in db", %{conn: conn} do
1875 post(conn, "/api/pleroma/admin/config", %{
1877 %{group: "pleroma", key: "key1", value: "value1"},
1880 key: "Ueberauth.Strategy.Twitter.OAuth",
1881 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
1887 ":nested_1" => "nested_value1",
1889 %{":nested_22" => "nested_value222"},
1890 %{":nested_33" => %{":nested_44" => "nested_444"}}
1898 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1899 %{"nested_4" => true}
1905 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
1910 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1915 assert json_response(conn, 200) == %{
1918 "group" => "pleroma",
1923 "group" => "ueberauth",
1924 "key" => "Ueberauth.Strategy.Twitter.OAuth",
1925 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
1928 "group" => "pleroma",
1931 ":nested_1" => "nested_value1",
1933 %{":nested_22" => "nested_value222"},
1934 %{":nested_33" => %{":nested_44" => "nested_444"}}
1939 "group" => "pleroma",
1942 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1943 %{"nested_4" => true}
1947 "group" => "pleroma",
1949 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
1954 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1959 assert Application.get_env(:pleroma, :key1) == "value1"
1961 assert Application.get_env(:pleroma, :key2) == %{
1962 nested_1: "nested_value1",
1964 %{nested_22: "nested_value222"},
1965 %{nested_33: %{nested_44: "nested_444"}}
1969 assert Application.get_env(:pleroma, :key3) == [
1970 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
1971 %{"nested_4" => true}
1974 assert Application.get_env(:pleroma, :key4) == %{
1975 "endpoint" => "https://example.com",
1979 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
1982 test "update config setting & delete", %{conn: conn} do
1983 config1 = insert(:config, key: "keyaa1")
1984 config2 = insert(:config, key: "keyaa2")
1988 key: "Ueberauth.Strategy.Microsoft.OAuth",
1989 value: :erlang.term_to_binary([])
1993 post(conn, "/api/pleroma/admin/config", %{
1995 %{group: config1.group, key: config1.key, value: "another_value"},
1996 %{group: config2.group, key: config2.key, delete: "true"},
1999 key: "Ueberauth.Strategy.Microsoft.OAuth",
2005 assert json_response(conn, 200) == %{
2008 "group" => "pleroma",
2009 "key" => config1.key,
2010 "value" => "another_value"
2015 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
2016 refute Application.get_env(:pleroma, :keyaa2)
2019 test "common config example", %{conn: conn} do
2021 post(conn, "/api/pleroma/admin/config", %{
2024 "group" => "pleroma",
2025 "key" => "Pleroma.Captcha.NotReal",
2027 %{"tuple" => [":enabled", false]},
2028 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2029 %{"tuple" => [":seconds_valid", 60]},
2030 %{"tuple" => [":path", ""]},
2031 %{"tuple" => [":key1", nil]},
2032 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2033 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
2034 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2035 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2036 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
2042 assert json_response(conn, 200) == %{
2045 "group" => "pleroma",
2046 "key" => "Pleroma.Captcha.NotReal",
2048 %{"tuple" => [":enabled", false]},
2049 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2050 %{"tuple" => [":seconds_valid", 60]},
2051 %{"tuple" => [":path", ""]},
2052 %{"tuple" => [":key1", nil]},
2053 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2054 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2055 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2056 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2057 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
2064 test "tuples with more than two values", %{conn: conn} do
2066 post(conn, "/api/pleroma/admin/config", %{
2069 "group" => "pleroma",
2070 "key" => "Pleroma.Web.Endpoint.NotReal",
2086 "/api/v1/streaming",
2087 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2094 "Phoenix.Endpoint.CowboyWebSocket",
2097 "Phoenix.Transports.WebSocket",
2100 "Pleroma.Web.Endpoint",
2101 "Pleroma.Web.UserSocket",
2112 "Phoenix.Endpoint.Cowboy2Handler",
2113 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2130 assert json_response(conn, 200) == %{
2133 "group" => "pleroma",
2134 "key" => "Pleroma.Web.Endpoint.NotReal",
2150 "/api/v1/streaming",
2151 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2158 "Phoenix.Endpoint.CowboyWebSocket",
2161 "Phoenix.Transports.WebSocket",
2164 "Pleroma.Web.Endpoint",
2165 "Pleroma.Web.UserSocket",
2176 "Phoenix.Endpoint.Cowboy2Handler",
2177 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2195 test "settings with nesting map", %{conn: conn} do
2197 post(conn, "/api/pleroma/admin/config", %{
2200 "group" => "pleroma",
2203 %{"tuple" => [":key2", "some_val"]},
2208 ":max_options" => 20,
2209 ":max_option_chars" => 200,
2210 ":min_expiration" => 0,
2211 ":max_expiration" => 31_536_000,
2213 ":max_options" => 20,
2214 ":max_option_chars" => 200,
2215 ":min_expiration" => 0,
2216 ":max_expiration" => 31_536_000
2226 assert json_response(conn, 200) ==
2230 "group" => "pleroma",
2233 %{"tuple" => [":key2", "some_val"]},
2238 ":max_expiration" => 31_536_000,
2239 ":max_option_chars" => 200,
2240 ":max_options" => 20,
2241 ":min_expiration" => 0,
2243 ":max_expiration" => 31_536_000,
2244 ":max_option_chars" => 200,
2245 ":max_options" => 20,
2246 ":min_expiration" => 0
2257 test "value as map", %{conn: conn} do
2259 post(conn, "/api/pleroma/admin/config", %{
2262 "group" => "pleroma",
2264 "value" => %{"key" => "some_val"}
2269 assert json_response(conn, 200) ==
2273 "group" => "pleroma",
2275 "value" => %{"key" => "some_val"}
2281 test "dispatch setting", %{conn: conn} do
2283 post(conn, "/api/pleroma/admin/config", %{
2286 "group" => "pleroma",
2287 "key" => "Pleroma.Web.Endpoint.NotReal",
2293 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2294 %{"tuple" => [":dispatch", ["{:_,
2296 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2297 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2298 {Phoenix.Transports.WebSocket,
2299 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2300 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2311 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2312 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2313 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2314 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2316 assert json_response(conn, 200) == %{
2319 "group" => "pleroma",
2320 "key" => "Pleroma.Web.Endpoint.NotReal",
2326 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2344 test "queues key as atom", %{conn: conn} do
2346 post(conn, "/api/pleroma/admin/config", %{
2352 %{"tuple" => [":federator_incoming", 50]},
2353 %{"tuple" => [":federator_outgoing", 50]},
2354 %{"tuple" => [":web_push", 50]},
2355 %{"tuple" => [":mailer", 10]},
2356 %{"tuple" => [":transmogrifier", 20]},
2357 %{"tuple" => [":scheduled_activities", 10]},
2358 %{"tuple" => [":background", 5]}
2364 assert json_response(conn, 200) == %{
2370 %{"tuple" => [":federator_incoming", 50]},
2371 %{"tuple" => [":federator_outgoing", 50]},
2372 %{"tuple" => [":web_push", 50]},
2373 %{"tuple" => [":mailer", 10]},
2374 %{"tuple" => [":transmogrifier", 20]},
2375 %{"tuple" => [":scheduled_activities", 10]},
2376 %{"tuple" => [":background", 5]}
2383 test "delete part of settings by atom subkeys", %{conn: conn} do
2387 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2391 post(conn, "/api/pleroma/admin/config", %{
2394 group: config.group,
2396 subkeys: [":subkey1", ":subkey3"],
2403 json_response(conn, 200) == %{
2406 "group" => "pleroma",
2408 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2416 describe "config mix tasks run" do
2417 setup %{conn: conn} do
2418 admin = insert(:user, is_admin: true)
2420 temp_file = "config/test.exported_from_db.secret.exs"
2422 Mix.shell(Mix.Shell.Quiet)
2425 Mix.shell(Mix.Shell.IO)
2426 :ok = File.rm(temp_file)
2429 %{conn: assign(conn, :user, admin), admin: admin}
2432 clear_config([:instance, :dynamic_configuration]) do
2433 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2436 clear_config([:feed, :post_title]) do
2437 Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
2440 test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
2441 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2442 conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
2443 assert json_response(conn, 200) == %{}
2444 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2448 |> assign(:user, admin)
2449 |> get("/api/pleroma/admin/config/migrate_from_db")
2451 assert json_response(conn, 200) == %{}
2452 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2456 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2458 admin = insert(:user, is_admin: true)
2459 user = insert(:user)
2461 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2462 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2463 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2465 insert(:note_activity, user: user, published: date1)
2466 insert(:note_activity, user: user, published: date2)
2467 insert(:note_activity, user: user, published: date3)
2471 |> assign(:user, admin)
2473 {:ok, conn: conn, user: user}
2476 test "renders user's statuses", %{conn: conn, user: user} do
2477 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2479 assert json_response(conn, 200) |> length() == 3
2482 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2483 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2485 assert json_response(conn, 200) |> length() == 2
2488 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2489 {:ok, _private_status} =
2490 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2492 {:ok, _public_status} =
2493 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2495 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2497 assert json_response(conn, 200) |> length() == 4
2500 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2501 {:ok, _private_status} =
2502 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2504 {:ok, _public_status} =
2505 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2507 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2509 assert json_response(conn, 200) |> length() == 5
2513 describe "GET /api/pleroma/admin/moderation_log" do
2514 setup %{conn: conn} do
2515 admin = insert(:user, is_admin: true)
2516 moderator = insert(:user, is_moderator: true)
2518 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
2521 test "returns the log", %{conn: conn, admin: admin} do
2522 Repo.insert(%ModerationLog{
2526 "nickname" => admin.nickname,
2529 action: "relay_follow",
2530 target: "https://example.org/relay"
2532 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2535 Repo.insert(%ModerationLog{
2539 "nickname" => admin.nickname,
2542 action: "relay_unfollow",
2543 target: "https://example.org/relay"
2545 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2548 conn = get(conn, "/api/pleroma/admin/moderation_log")
2550 response = json_response(conn, 200)
2551 [first_entry, second_entry] = response["items"]
2553 assert response["total"] == 2
2554 assert first_entry["data"]["action"] == "relay_unfollow"
2556 assert first_entry["message"] ==
2557 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2559 assert second_entry["data"]["action"] == "relay_follow"
2561 assert second_entry["message"] ==
2562 "@#{admin.nickname} followed relay: https://example.org/relay"
2565 test "returns the log with pagination", %{conn: conn, admin: admin} do
2566 Repo.insert(%ModerationLog{
2570 "nickname" => admin.nickname,
2573 action: "relay_follow",
2574 target: "https://example.org/relay"
2576 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2579 Repo.insert(%ModerationLog{
2583 "nickname" => admin.nickname,
2586 action: "relay_unfollow",
2587 target: "https://example.org/relay"
2589 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2592 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2594 response1 = json_response(conn1, 200)
2595 [first_entry] = response1["items"]
2597 assert response1["total"] == 2
2598 assert response1["items"] |> length() == 1
2599 assert first_entry["data"]["action"] == "relay_unfollow"
2601 assert first_entry["message"] ==
2602 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2604 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2606 response2 = json_response(conn2, 200)
2607 [second_entry] = response2["items"]
2609 assert response2["total"] == 2
2610 assert response2["items"] |> length() == 1
2611 assert second_entry["data"]["action"] == "relay_follow"
2613 assert second_entry["message"] ==
2614 "@#{admin.nickname} followed relay: https://example.org/relay"
2617 test "filters log by date", %{conn: conn, admin: admin} do
2618 first_date = "2017-08-15T15:47:06Z"
2619 second_date = "2017-08-20T15:47:06Z"
2621 Repo.insert(%ModerationLog{
2625 "nickname" => admin.nickname,
2628 action: "relay_follow",
2629 target: "https://example.org/relay"
2631 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2634 Repo.insert(%ModerationLog{
2638 "nickname" => admin.nickname,
2641 action: "relay_unfollow",
2642 target: "https://example.org/relay"
2644 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2650 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2653 response1 = json_response(conn1, 200)
2654 [first_entry] = response1["items"]
2656 assert response1["total"] == 1
2657 assert first_entry["data"]["action"] == "relay_unfollow"
2659 assert first_entry["message"] ==
2660 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2663 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2664 Repo.insert(%ModerationLog{
2668 "nickname" => admin.nickname,
2671 action: "relay_follow",
2672 target: "https://example.org/relay"
2676 Repo.insert(%ModerationLog{
2679 "id" => moderator.id,
2680 "nickname" => moderator.nickname,
2683 action: "relay_unfollow",
2684 target: "https://example.org/relay"
2688 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2690 response1 = json_response(conn1, 200)
2691 [first_entry] = response1["items"]
2693 assert response1["total"] == 1
2694 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2697 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2698 ModerationLog.insert_log(%{
2700 action: "relay_follow",
2701 target: "https://example.org/relay"
2704 ModerationLog.insert_log(%{
2706 action: "relay_unfollow",
2707 target: "https://example.org/relay"
2710 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2712 response1 = json_response(conn1, 200)
2713 [first_entry] = response1["items"]
2715 assert response1["total"] == 1
2717 assert get_in(first_entry, ["data", "message"]) ==
2718 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2722 describe "PATCH /users/:nickname/force_password_reset" do
2723 setup %{conn: conn} do
2724 admin = insert(:user, is_admin: true)
2725 user = insert(:user)
2727 %{conn: assign(conn, :user, admin), admin: admin, user: user}
2730 test "sets password_reset_pending to true", %{admin: admin, user: user} do
2731 assert user.password_reset_pending == false
2735 |> assign(:user, admin)
2736 |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
2738 assert json_response(conn, 204) == ""
2740 ObanHelpers.perform_all()
2742 assert User.get_by_id(user.id).password_reset_pending == true
2746 describe "relays" do
2747 setup %{conn: conn} do
2748 admin = insert(:user, is_admin: true)
2750 %{conn: assign(conn, :user, admin), admin: admin}
2753 test "POST /relay", %{admin: admin} do
2756 |> assign(:user, admin)
2757 |> post("/api/pleroma/admin/relay", %{
2758 relay_url: "http://mastodon.example.org/users/admin"
2761 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2763 log_entry = Repo.one(ModerationLog)
2765 assert ModerationLog.get_log_entry_message(log_entry) ==
2766 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2769 test "GET /relay", %{admin: admin} do
2770 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
2772 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
2773 |> Enum.each(fn ap_id ->
2774 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
2775 User.follow(relay_user, user)
2780 |> assign(:user, admin)
2781 |> get("/api/pleroma/admin/relay")
2783 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
2786 test "DELETE /relay", %{admin: admin} do
2788 |> assign(:user, admin)
2789 |> post("/api/pleroma/admin/relay", %{
2790 relay_url: "http://mastodon.example.org/users/admin"
2795 |> assign(:user, admin)
2796 |> delete("/api/pleroma/admin/relay", %{
2797 relay_url: "http://mastodon.example.org/users/admin"
2800 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2802 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
2804 assert ModerationLog.get_log_entry_message(log_entry_one) ==
2805 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2807 assert ModerationLog.get_log_entry_message(log_entry_two) ==
2808 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
2812 describe "instances" do
2813 test "GET /instances/:instance/statuses" do
2814 admin = insert(:user, is_admin: true)
2815 user = insert(:user, local: false, nickname: "archaeme@archae.me")
2816 user2 = insert(:user, local: false, nickname: "test@test.com")
2817 insert_pair(:note_activity, user: user)
2818 insert(:note_activity, user: user2)
2822 |> assign(:user, admin)
2823 |> get("/api/pleroma/admin/instances/archae.me/statuses")
2825 response = json_response(conn, 200)
2827 assert length(response) == 2
2831 |> assign(:user, admin)
2832 |> get("/api/pleroma/admin/instances/test.com/statuses")
2834 response = json_response(conn, 200)
2836 assert length(response) == 1
2840 |> assign(:user, admin)
2841 |> get("/api/pleroma/admin/instances/nonexistent.com/statuses")
2843 response = json_response(conn, 200)
2845 assert length(response) == 0
2849 describe "PATCH /confirm_email" do
2850 setup %{conn: conn} do
2851 admin = insert(:user, is_admin: true)
2853 %{conn: assign(conn, :user, admin), admin: admin}
2856 test "it confirms emails of two users", %{admin: admin} do
2857 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
2859 assert first_user.confirmation_pending == true
2860 assert second_user.confirmation_pending == true
2863 |> assign(:user, admin)
2864 |> patch("/api/pleroma/admin/users/confirm_email", %{
2866 first_user.nickname,
2867 second_user.nickname
2871 assert first_user.confirmation_pending == true
2872 assert second_user.confirmation_pending == true
2874 log_entry = Repo.one(ModerationLog)
2876 assert ModerationLog.get_log_entry_message(log_entry) ==
2877 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
2878 second_user.nickname
2883 describe "PATCH /resend_confirmation_email" do
2884 setup %{conn: conn} do
2885 admin = insert(:user, is_admin: true)
2887 %{conn: assign(conn, :user, admin), admin: admin}
2890 test "it resend emails for two users", %{admin: admin} do
2891 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
2894 |> assign(:user, admin)
2895 |> patch("/api/pleroma/admin/users/resend_confirmation_email", %{
2897 first_user.nickname,
2898 second_user.nickname
2902 log_entry = Repo.one(ModerationLog)
2904 assert ModerationLog.get_log_entry_message(log_entry) ==
2905 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
2906 second_user.nickname
2911 describe "POST /reports/:id/notes" do
2913 admin = insert(:user, is_admin: true)
2914 [reporter, target_user] = insert_pair(:user)
2915 activity = insert(:note_activity, user: target_user)
2917 {:ok, %{id: report_id}} =
2918 CommonAPI.report(reporter, %{
2919 "account_id" => target_user.id,
2920 "comment" => "I feel offended",
2921 "status_ids" => [activity.id]
2925 |> assign(:user, admin)
2926 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
2927 content: "this is disgusting!"
2931 |> assign(:user, admin)
2932 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
2933 content: "this is disgusting2!"
2938 report_id: report_id,
2943 test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
2944 [note, _] = Repo.all(ReportNote)
2947 activity_id: ^report_id,
2948 content: "this is disgusting!",
2953 test "it returns reports with notes", %{admin: admin} do
2956 |> assign(:user, admin)
2957 |> get("/api/pleroma/admin/reports")
2959 response = json_response(conn, 200)
2960 notes = hd(response["reports"])["notes"]
2963 assert note["user"]["nickname"] == admin.nickname
2964 assert note["content"] == "this is disgusting!"
2965 assert note["created_at"]
2966 assert response["total"] == 1
2969 test "it deletes the note", %{admin: admin, report_id: report_id} do
2970 assert ReportNote |> Repo.all() |> length() == 2
2972 [note, _] = Repo.all(ReportNote)
2975 |> assign(:user, admin)
2976 |> delete("/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
2978 assert ReportNote |> Repo.all() |> length() == 1
2983 # Needed for testing
2984 defmodule Pleroma.Web.Endpoint.NotReal do
2987 defmodule Pleroma.Captcha.NotReal do