1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 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
9 import ExUnit.CaptureLog
11 import Pleroma.Factory
13 alias Pleroma.Activity
15 alias Pleroma.ConfigDB
18 alias Pleroma.ModerationLog
20 alias Pleroma.ReportNote
21 alias Pleroma.Tests.ObanHelpers
24 alias Pleroma.Web.ActivityPub.Relay
25 alias Pleroma.Web.CommonAPI
26 alias Pleroma.Web.MediaProxy
29 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
35 admin = insert(:user, is_admin: true)
36 token = insert(:oauth_admin_token, user: admin)
40 |> assign(:user, admin)
41 |> assign(:token, token)
43 {:ok, %{admin: admin, token: token, conn: conn}}
46 describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
47 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
49 test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
52 url = "/api/pleroma/admin/users/#{user.nickname}"
54 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
55 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
56 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
58 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
59 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
62 for good_token <- [good_token1, good_token2, good_token3] do
65 |> assign(:user, admin)
66 |> assign(:token, good_token)
69 assert json_response(conn, 200)
72 for good_token <- [good_token1, good_token2, good_token3] do
76 |> assign(:token, good_token)
79 assert json_response(conn, :forbidden)
82 for bad_token <- [bad_token1, bad_token2, bad_token3] do
85 |> assign(:user, admin)
86 |> assign(:token, bad_token)
89 assert json_response(conn, :forbidden)
94 describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
95 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
97 test "GET /api/pleroma/admin/users/:nickname requires " <>
98 "read:accounts or admin:read:accounts or broader scope",
101 url = "/api/pleroma/admin/users/#{user.nickname}"
103 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
104 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
105 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
106 good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
107 good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])
109 good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]
111 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
112 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
115 for good_token <- good_tokens do
118 |> assign(:user, admin)
119 |> assign(:token, good_token)
122 assert json_response(conn, 200)
125 for good_token <- good_tokens do
128 |> assign(:user, nil)
129 |> assign(:token, good_token)
132 assert json_response(conn, :forbidden)
135 for bad_token <- [bad_token1, bad_token2, bad_token3] do
138 |> assign(:user, admin)
139 |> assign(:token, bad_token)
142 assert json_response(conn, :forbidden)
147 describe "DELETE /api/pleroma/admin/users" do
148 test "single user", %{admin: admin, conn: conn} do
150 clear_config([:instance, :federating], true)
152 with_mock Pleroma.Web.Federator,
153 publish: fn _ -> nil end do
156 |> put_req_header("accept", "application/json")
157 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
159 ObanHelpers.perform_all()
161 assert User.get_by_nickname(user.nickname).deactivated
163 log_entry = Repo.one(ModerationLog)
165 assert ModerationLog.get_log_entry_message(log_entry) ==
166 "@#{admin.nickname} deleted users: @#{user.nickname}"
168 assert json_response(conn, 200) == [user.nickname]
170 assert called(Pleroma.Web.Federator.publish(:_))
174 test "multiple users", %{admin: admin, conn: conn} do
175 user_one = insert(:user)
176 user_two = insert(:user)
180 |> put_req_header("accept", "application/json")
181 |> delete("/api/pleroma/admin/users", %{
182 nicknames: [user_one.nickname, user_two.nickname]
185 log_entry = Repo.one(ModerationLog)
187 assert ModerationLog.get_log_entry_message(log_entry) ==
188 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
190 response = json_response(conn, 200)
191 assert response -- [user_one.nickname, user_two.nickname] == []
195 describe "/api/pleroma/admin/users" do
196 test "Create", %{conn: conn} do
199 |> put_req_header("accept", "application/json")
200 |> post("/api/pleroma/admin/users", %{
203 "nickname" => "lain",
204 "email" => "lain@example.org",
208 "nickname" => "lain2",
209 "email" => "lain2@example.org",
215 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
216 assert response == ["success", "success"]
218 log_entry = Repo.one(ModerationLog)
220 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
223 test "Cannot create user with existing email", %{conn: conn} do
228 |> put_req_header("accept", "application/json")
229 |> post("/api/pleroma/admin/users", %{
232 "nickname" => "lain",
233 "email" => user.email,
239 assert json_response(conn, 409) == [
243 "email" => user.email,
246 "error" => "email has already been taken",
252 test "Cannot create user with existing nickname", %{conn: conn} do
257 |> put_req_header("accept", "application/json")
258 |> post("/api/pleroma/admin/users", %{
261 "nickname" => user.nickname,
262 "email" => "someuser@plerama.social",
268 assert json_response(conn, 409) == [
272 "email" => "someuser@plerama.social",
273 "nickname" => user.nickname
275 "error" => "nickname has already been taken",
281 test "Multiple user creation works in transaction", %{conn: conn} do
286 |> put_req_header("accept", "application/json")
287 |> post("/api/pleroma/admin/users", %{
290 "nickname" => "newuser",
291 "email" => "newuser@pleroma.social",
295 "nickname" => "lain",
296 "email" => user.email,
302 assert json_response(conn, 409) == [
306 "email" => user.email,
309 "error" => "email has already been taken",
315 "email" => "newuser@pleroma.social",
316 "nickname" => "newuser"
323 assert User.get_by_nickname("newuser") === nil
327 describe "/api/pleroma/admin/users/:nickname" do
328 test "Show", %{conn: conn} do
331 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
334 "deactivated" => false,
335 "id" => to_string(user.id),
337 "nickname" => user.nickname,
338 "roles" => %{"admin" => false, "moderator" => false},
340 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
341 "display_name" => HTML.strip_tags(user.name || user.nickname),
342 "confirmation_pending" => false
345 assert expected == json_response(conn, 200)
348 test "when the user doesn't exist", %{conn: conn} do
351 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
353 assert %{"error" => "Not found"} == json_response(conn, 404)
357 describe "/api/pleroma/admin/users/follow" do
358 test "allows to force-follow another user", %{admin: admin, conn: conn} do
360 follower = insert(:user)
363 |> put_req_header("accept", "application/json")
364 |> post("/api/pleroma/admin/users/follow", %{
365 "follower" => follower.nickname,
366 "followed" => user.nickname
369 user = User.get_cached_by_id(user.id)
370 follower = User.get_cached_by_id(follower.id)
372 assert User.following?(follower, user)
374 log_entry = Repo.one(ModerationLog)
376 assert ModerationLog.get_log_entry_message(log_entry) ==
377 "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
381 describe "/api/pleroma/admin/users/unfollow" do
382 test "allows to force-unfollow another user", %{admin: admin, conn: conn} do
384 follower = insert(:user)
386 User.follow(follower, user)
389 |> put_req_header("accept", "application/json")
390 |> post("/api/pleroma/admin/users/unfollow", %{
391 "follower" => follower.nickname,
392 "followed" => user.nickname
395 user = User.get_cached_by_id(user.id)
396 follower = User.get_cached_by_id(follower.id)
398 refute User.following?(follower, user)
400 log_entry = Repo.one(ModerationLog)
402 assert ModerationLog.get_log_entry_message(log_entry) ==
403 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
407 describe "PUT /api/pleroma/admin/users/tag" do
408 setup %{conn: conn} do
409 user1 = insert(:user, %{tags: ["x"]})
410 user2 = insert(:user, %{tags: ["y"]})
411 user3 = insert(:user, %{tags: ["unchanged"]})
415 |> put_req_header("accept", "application/json")
417 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
418 "#{user2.nickname}&tags[]=foo&tags[]=bar"
421 %{conn: conn, user1: user1, user2: user2, user3: user3}
424 test "it appends specified tags to users with specified nicknames", %{
430 assert json_response(conn, :no_content)
431 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
432 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
434 log_entry = Repo.one(ModerationLog)
437 [user1.nickname, user2.nickname]
438 |> Enum.map(&"@#{&1}")
441 tags = ["foo", "bar"] |> Enum.join(", ")
443 assert ModerationLog.get_log_entry_message(log_entry) ==
444 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
447 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
448 assert json_response(conn, :no_content)
449 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
453 describe "DELETE /api/pleroma/admin/users/tag" do
454 setup %{conn: conn} do
455 user1 = insert(:user, %{tags: ["x"]})
456 user2 = insert(:user, %{tags: ["y", "z"]})
457 user3 = insert(:user, %{tags: ["unchanged"]})
461 |> put_req_header("accept", "application/json")
463 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
464 "#{user2.nickname}&tags[]=x&tags[]=z"
467 %{conn: conn, user1: user1, user2: user2, user3: user3}
470 test "it removes specified tags from users with specified nicknames", %{
476 assert json_response(conn, :no_content)
477 assert User.get_cached_by_id(user1.id).tags == []
478 assert User.get_cached_by_id(user2.id).tags == ["y"]
480 log_entry = Repo.one(ModerationLog)
483 [user1.nickname, user2.nickname]
484 |> Enum.map(&"@#{&1}")
487 tags = ["x", "z"] |> Enum.join(", ")
489 assert ModerationLog.get_log_entry_message(log_entry) ==
490 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
493 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
494 assert json_response(conn, :no_content)
495 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
499 describe "/api/pleroma/admin/users/:nickname/permission_group" do
500 test "GET is giving user_info", %{admin: admin, conn: conn} do
503 |> put_req_header("accept", "application/json")
504 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
506 assert json_response(conn, 200) == %{
508 "is_moderator" => false
512 test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do
517 |> put_req_header("accept", "application/json")
518 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
520 assert json_response(conn, 200) == %{
524 log_entry = Repo.one(ModerationLog)
526 assert ModerationLog.get_log_entry_message(log_entry) ==
527 "@#{admin.nickname} made @#{user.nickname} admin"
530 test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do
531 user_one = insert(:user)
532 user_two = insert(:user)
536 |> put_req_header("accept", "application/json")
537 |> post("/api/pleroma/admin/users/permission_group/admin", %{
538 nicknames: [user_one.nickname, user_two.nickname]
541 assert json_response(conn, 200) == %{"is_admin" => true}
543 log_entry = Repo.one(ModerationLog)
545 assert ModerationLog.get_log_entry_message(log_entry) ==
546 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
549 test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do
550 user = insert(:user, is_admin: true)
554 |> put_req_header("accept", "application/json")
555 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
557 assert json_response(conn, 200) == %{"is_admin" => false}
559 log_entry = Repo.one(ModerationLog)
561 assert ModerationLog.get_log_entry_message(log_entry) ==
562 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
565 test "/:right DELETE, can remove from a permission group (multiple)", %{
569 user_one = insert(:user, is_admin: true)
570 user_two = insert(:user, is_admin: true)
574 |> put_req_header("accept", "application/json")
575 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
576 nicknames: [user_one.nickname, user_two.nickname]
579 assert json_response(conn, 200) == %{"is_admin" => false}
581 log_entry = Repo.one(ModerationLog)
583 assert ModerationLog.get_log_entry_message(log_entry) ==
584 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
590 test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
595 |> put_req_header("accept", "application/json")
596 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
598 resp = json_response(conn, 200)
600 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
603 describe "GET /api/pleroma/admin/users" do
604 test "renders users array for the first page", %{conn: conn, admin: admin} do
605 user = insert(:user, local: false, tags: ["foo", "bar"])
606 conn = get(conn, "/api/pleroma/admin/users?page=1")
611 "deactivated" => admin.deactivated,
613 "nickname" => admin.nickname,
614 "roles" => %{"admin" => true, "moderator" => false},
617 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
618 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
619 "confirmation_pending" => false
622 "deactivated" => user.deactivated,
624 "nickname" => user.nickname,
625 "roles" => %{"admin" => false, "moderator" => 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
633 |> Enum.sort_by(& &1["nickname"])
635 assert json_response(conn, 200) == %{
642 test "pagination works correctly with service users", %{conn: conn} do
643 service1 = insert(:user, ap_id: Web.base_url() <> "/relay")
644 service2 = insert(:user, ap_id: Web.base_url() <> "/internal/fetch")
645 insert_list(25, :user)
647 assert %{"count" => 26, "page_size" => 10, "users" => users1} =
649 |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"})
650 |> json_response(200)
652 assert Enum.count(users1) == 10
653 assert service1 not in [users1]
654 assert service2 not in [users1]
656 assert %{"count" => 26, "page_size" => 10, "users" => users2} =
658 |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"})
659 |> json_response(200)
661 assert Enum.count(users2) == 10
662 assert service1 not in [users2]
663 assert service2 not in [users2]
665 assert %{"count" => 26, "page_size" => 10, "users" => users3} =
667 |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"})
668 |> json_response(200)
670 assert Enum.count(users3) == 6
671 assert service1 not in [users3]
672 assert service2 not in [users3]
675 test "renders empty array for the second page", %{conn: conn} do
678 conn = get(conn, "/api/pleroma/admin/users?page=2")
680 assert json_response(conn, 200) == %{
687 test "regular search", %{conn: conn} do
688 user = insert(:user, nickname: "bob")
690 conn = get(conn, "/api/pleroma/admin/users?query=bo")
692 assert json_response(conn, 200) == %{
697 "deactivated" => user.deactivated,
699 "nickname" => user.nickname,
700 "roles" => %{"admin" => false, "moderator" => false},
703 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
704 "display_name" => HTML.strip_tags(user.name || user.nickname),
705 "confirmation_pending" => false
711 test "search by domain", %{conn: conn} do
712 user = insert(:user, nickname: "nickname@domain.com")
715 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
717 assert json_response(conn, 200) == %{
722 "deactivated" => user.deactivated,
724 "nickname" => user.nickname,
725 "roles" => %{"admin" => false, "moderator" => false},
728 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
729 "display_name" => HTML.strip_tags(user.name || user.nickname),
730 "confirmation_pending" => false
736 test "search by full nickname", %{conn: conn} do
737 user = insert(:user, nickname: "nickname@domain.com")
740 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
742 assert json_response(conn, 200) == %{
747 "deactivated" => user.deactivated,
749 "nickname" => user.nickname,
750 "roles" => %{"admin" => false, "moderator" => false},
753 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
754 "display_name" => HTML.strip_tags(user.name || user.nickname),
755 "confirmation_pending" => false
761 test "search by display name", %{conn: conn} do
762 user = insert(:user, name: "Display name")
765 conn = get(conn, "/api/pleroma/admin/users?name=display")
767 assert json_response(conn, 200) == %{
772 "deactivated" => user.deactivated,
774 "nickname" => user.nickname,
775 "roles" => %{"admin" => false, "moderator" => false},
778 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
779 "display_name" => HTML.strip_tags(user.name || user.nickname),
780 "confirmation_pending" => false
786 test "search by email", %{conn: conn} do
787 user = insert(:user, email: "email@example.com")
790 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
792 assert json_response(conn, 200) == %{
797 "deactivated" => user.deactivated,
799 "nickname" => user.nickname,
800 "roles" => %{"admin" => false, "moderator" => false},
803 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
804 "display_name" => HTML.strip_tags(user.name || user.nickname),
805 "confirmation_pending" => false
811 test "regular search with page size", %{conn: conn} do
812 user = insert(:user, nickname: "aalice")
813 user2 = insert(:user, nickname: "alice")
815 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
817 assert json_response(conn1, 200) == %{
822 "deactivated" => user.deactivated,
824 "nickname" => user.nickname,
825 "roles" => %{"admin" => false, "moderator" => false},
828 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
829 "display_name" => HTML.strip_tags(user.name || user.nickname),
830 "confirmation_pending" => false
835 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
837 assert json_response(conn2, 200) == %{
842 "deactivated" => user2.deactivated,
844 "nickname" => user2.nickname,
845 "roles" => %{"admin" => false, "moderator" => false},
848 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
849 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
850 "confirmation_pending" => false
856 test "only local users" do
857 admin = insert(:user, is_admin: true, nickname: "john")
858 token = insert(:oauth_admin_token, user: admin)
859 user = insert(:user, nickname: "bob")
861 insert(:user, nickname: "bobb", local: false)
865 |> assign(:user, admin)
866 |> assign(:token, token)
867 |> get("/api/pleroma/admin/users?query=bo&filters=local")
869 assert json_response(conn, 200) == %{
874 "deactivated" => user.deactivated,
876 "nickname" => user.nickname,
877 "roles" => %{"admin" => false, "moderator" => false},
880 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
881 "display_name" => HTML.strip_tags(user.name || user.nickname),
882 "confirmation_pending" => false
888 test "only local users with no query", %{conn: conn, admin: old_admin} do
889 admin = insert(:user, is_admin: true, nickname: "john")
890 user = insert(:user, nickname: "bob")
892 insert(:user, nickname: "bobb", local: false)
894 conn = get(conn, "/api/pleroma/admin/users?filters=local")
899 "deactivated" => user.deactivated,
901 "nickname" => user.nickname,
902 "roles" => %{"admin" => false, "moderator" => false},
905 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
906 "display_name" => HTML.strip_tags(user.name || user.nickname),
907 "confirmation_pending" => false
910 "deactivated" => admin.deactivated,
912 "nickname" => admin.nickname,
913 "roles" => %{"admin" => true, "moderator" => false},
916 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
917 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
918 "confirmation_pending" => false
921 "deactivated" => false,
922 "id" => old_admin.id,
924 "nickname" => old_admin.nickname,
925 "roles" => %{"admin" => true, "moderator" => false},
927 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
928 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
929 "confirmation_pending" => false
932 |> Enum.sort_by(& &1["nickname"])
934 assert json_response(conn, 200) == %{
941 test "load only admins", %{conn: conn, admin: admin} do
942 second_admin = insert(:user, is_admin: true)
946 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
951 "deactivated" => false,
953 "nickname" => admin.nickname,
954 "roles" => %{"admin" => true, "moderator" => false},
955 "local" => admin.local,
957 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
958 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
959 "confirmation_pending" => false
962 "deactivated" => false,
963 "id" => second_admin.id,
964 "nickname" => second_admin.nickname,
965 "roles" => %{"admin" => true, "moderator" => false},
966 "local" => second_admin.local,
968 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
969 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
970 "confirmation_pending" => false
973 |> Enum.sort_by(& &1["nickname"])
975 assert json_response(conn, 200) == %{
982 test "load only moderators", %{conn: conn} do
983 moderator = insert(:user, is_moderator: true)
987 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
989 assert json_response(conn, 200) == %{
994 "deactivated" => false,
995 "id" => moderator.id,
996 "nickname" => moderator.nickname,
997 "roles" => %{"admin" => false, "moderator" => true},
998 "local" => moderator.local,
1000 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
1001 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
1002 "confirmation_pending" => false
1008 test "load users with tags list", %{conn: conn} do
1009 user1 = insert(:user, tags: ["first"])
1010 user2 = insert(:user, tags: ["second"])
1014 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
1019 "deactivated" => false,
1021 "nickname" => user1.nickname,
1022 "roles" => %{"admin" => false, "moderator" => false},
1023 "local" => user1.local,
1024 "tags" => ["first"],
1025 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
1026 "display_name" => HTML.strip_tags(user1.name || user1.nickname),
1027 "confirmation_pending" => false
1030 "deactivated" => false,
1032 "nickname" => user2.nickname,
1033 "roles" => %{"admin" => false, "moderator" => false},
1034 "local" => user2.local,
1035 "tags" => ["second"],
1036 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1037 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
1038 "confirmation_pending" => false
1041 |> Enum.sort_by(& &1["nickname"])
1043 assert json_response(conn, 200) == %{
1050 test "it works with multiple filters" do
1051 admin = insert(:user, nickname: "john", is_admin: true)
1052 token = insert(:oauth_admin_token, user: admin)
1053 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1055 insert(:user, nickname: "ken", local: true, deactivated: true)
1056 insert(:user, nickname: "bobb", local: false, deactivated: false)
1060 |> assign(:user, admin)
1061 |> assign(:token, token)
1062 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1064 assert json_response(conn, 200) == %{
1069 "deactivated" => user.deactivated,
1071 "nickname" => user.nickname,
1072 "roles" => %{"admin" => false, "moderator" => false},
1073 "local" => user.local,
1075 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1076 "display_name" => HTML.strip_tags(user.name || user.nickname),
1077 "confirmation_pending" => false
1083 test "it omits relay user", %{admin: admin, conn: conn} do
1084 assert %User{} = Relay.get_actor()
1086 conn = get(conn, "/api/pleroma/admin/users")
1088 assert json_response(conn, 200) == %{
1093 "deactivated" => admin.deactivated,
1095 "nickname" => admin.nickname,
1096 "roles" => %{"admin" => true, "moderator" => false},
1099 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1100 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
1101 "confirmation_pending" => false
1108 test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
1109 user_one = insert(:user, deactivated: true)
1110 user_two = insert(:user, deactivated: true)
1115 "/api/pleroma/admin/users/activate",
1116 %{nicknames: [user_one.nickname, user_two.nickname]}
1119 response = json_response(conn, 200)
1120 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1122 log_entry = Repo.one(ModerationLog)
1124 assert ModerationLog.get_log_entry_message(log_entry) ==
1125 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1128 test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
1129 user_one = insert(:user, deactivated: false)
1130 user_two = insert(:user, deactivated: false)
1135 "/api/pleroma/admin/users/deactivate",
1136 %{nicknames: [user_one.nickname, user_two.nickname]}
1139 response = json_response(conn, 200)
1140 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1142 log_entry = Repo.one(ModerationLog)
1144 assert ModerationLog.get_log_entry_message(log_entry) ==
1145 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1148 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
1149 user = insert(:user)
1151 conn = patch(conn, "/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1153 assert json_response(conn, 200) ==
1155 "deactivated" => !user.deactivated,
1157 "nickname" => user.nickname,
1158 "roles" => %{"admin" => false, "moderator" => false},
1161 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1162 "display_name" => HTML.strip_tags(user.name || user.nickname),
1163 "confirmation_pending" => false
1166 log_entry = Repo.one(ModerationLog)
1168 assert ModerationLog.get_log_entry_message(log_entry) ==
1169 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1172 describe "PUT disable_mfa" do
1173 test "returns 200 and disable 2fa", %{conn: conn} do
1176 multi_factor_authentication_settings: %MFA.Settings{
1178 totp: %MFA.Settings.TOTP{secret: "otp_secret", confirmed: true}
1184 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: user.nickname})
1185 |> json_response(200)
1187 assert response == user.nickname
1188 mfa_settings = refresh_record(user).multi_factor_authentication_settings
1190 refute mfa_settings.enabled
1191 refute mfa_settings.totp.confirmed
1194 test "returns 404 if user not found", %{conn: conn} do
1197 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
1198 |> json_response(404)
1200 assert response == %{"error" => "Not found"}
1204 describe "GET /api/pleroma/admin/reports/:id" do
1205 test "returns report by its id", %{conn: conn} do
1206 [reporter, target_user] = insert_pair(:user)
1207 activity = insert(:note_activity, user: target_user)
1209 {:ok, %{id: report_id}} =
1210 CommonAPI.report(reporter, %{
1211 account_id: target_user.id,
1212 comment: "I feel offended",
1213 status_ids: [activity.id]
1218 |> get("/api/pleroma/admin/reports/#{report_id}")
1219 |> json_response(:ok)
1221 assert response["id"] == report_id
1224 test "returns 404 when report id is invalid", %{conn: conn} do
1225 conn = get(conn, "/api/pleroma/admin/reports/test")
1227 assert json_response(conn, :not_found) == %{"error" => "Not found"}
1231 describe "PATCH /api/pleroma/admin/reports" do
1233 [reporter, target_user] = insert_pair(:user)
1234 activity = insert(:note_activity, user: target_user)
1236 {:ok, %{id: report_id}} =
1237 CommonAPI.report(reporter, %{
1238 account_id: target_user.id,
1239 comment: "I feel offended",
1240 status_ids: [activity.id]
1243 {:ok, %{id: second_report_id}} =
1244 CommonAPI.report(reporter, %{
1245 account_id: target_user.id,
1246 comment: "I feel very offended",
1247 status_ids: [activity.id]
1252 second_report_id: second_report_id
1256 test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} do
1257 read_token = insert(:oauth_token, user: admin, scopes: ["admin:read"])
1258 write_token = insert(:oauth_token, user: admin, scopes: ["admin:write:reports"])
1262 |> assign(:token, read_token)
1263 |> patch("/api/pleroma/admin/reports", %{
1264 "reports" => [%{"state" => "resolved", "id" => id}]
1266 |> json_response(403)
1268 assert response == %{
1269 "error" => "Insufficient permissions: admin:write:reports."
1273 |> assign(:token, write_token)
1274 |> patch("/api/pleroma/admin/reports", %{
1275 "reports" => [%{"state" => "resolved", "id" => id}]
1277 |> json_response(:no_content)
1280 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1282 |> patch("/api/pleroma/admin/reports", %{
1284 %{"state" => "resolved", "id" => id}
1287 |> json_response(:no_content)
1289 activity = Activity.get_by_id(id)
1290 assert activity.data["state"] == "resolved"
1292 log_entry = Repo.one(ModerationLog)
1294 assert ModerationLog.get_log_entry_message(log_entry) ==
1295 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1298 test "closes report", %{conn: conn, id: id, admin: admin} do
1300 |> patch("/api/pleroma/admin/reports", %{
1302 %{"state" => "closed", "id" => id}
1305 |> json_response(:no_content)
1307 activity = Activity.get_by_id(id)
1308 assert activity.data["state"] == "closed"
1310 log_entry = Repo.one(ModerationLog)
1312 assert ModerationLog.get_log_entry_message(log_entry) ==
1313 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1316 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1319 |> patch("/api/pleroma/admin/reports", %{
1321 %{"state" => "test", "id" => id}
1325 assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
1328 test "returns 404 when report is not exist", %{conn: conn} do
1331 |> patch("/api/pleroma/admin/reports", %{
1333 %{"state" => "closed", "id" => "test"}
1337 assert hd(json_response(conn, :bad_request))["error"] == "not_found"
1340 test "updates state of multiple reports", %{
1344 second_report_id: second_report_id
1347 |> patch("/api/pleroma/admin/reports", %{
1349 %{"state" => "resolved", "id" => id},
1350 %{"state" => "closed", "id" => second_report_id}
1353 |> json_response(:no_content)
1355 activity = Activity.get_by_id(id)
1356 second_activity = Activity.get_by_id(second_report_id)
1357 assert activity.data["state"] == "resolved"
1358 assert second_activity.data["state"] == "closed"
1360 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
1362 assert ModerationLog.get_log_entry_message(first_log_entry) ==
1363 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1365 assert ModerationLog.get_log_entry_message(second_log_entry) ==
1366 "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
1370 describe "GET /api/pleroma/admin/reports" do
1371 test "returns empty response when no reports created", %{conn: conn} do
1374 |> get("/api/pleroma/admin/reports")
1375 |> json_response(:ok)
1377 assert Enum.empty?(response["reports"])
1378 assert response["total"] == 0
1381 test "returns reports", %{conn: conn} do
1382 [reporter, target_user] = insert_pair(:user)
1383 activity = insert(:note_activity, user: target_user)
1385 {:ok, %{id: report_id}} =
1386 CommonAPI.report(reporter, %{
1387 account_id: target_user.id,
1388 comment: "I feel offended",
1389 status_ids: [activity.id]
1394 |> get("/api/pleroma/admin/reports")
1395 |> json_response(:ok)
1397 [report] = response["reports"]
1399 assert length(response["reports"]) == 1
1400 assert report["id"] == report_id
1402 assert response["total"] == 1
1405 test "returns reports with specified state", %{conn: conn} do
1406 [reporter, target_user] = insert_pair(:user)
1407 activity = insert(:note_activity, user: target_user)
1409 {:ok, %{id: first_report_id}} =
1410 CommonAPI.report(reporter, %{
1411 account_id: target_user.id,
1412 comment: "I feel offended",
1413 status_ids: [activity.id]
1416 {:ok, %{id: second_report_id}} =
1417 CommonAPI.report(reporter, %{
1418 account_id: target_user.id,
1419 comment: "I don't like this user"
1422 CommonAPI.update_report_state(second_report_id, "closed")
1426 |> get("/api/pleroma/admin/reports", %{
1429 |> json_response(:ok)
1431 [open_report] = response["reports"]
1433 assert length(response["reports"]) == 1
1434 assert open_report["id"] == first_report_id
1436 assert response["total"] == 1
1440 |> get("/api/pleroma/admin/reports", %{
1443 |> json_response(:ok)
1445 [closed_report] = response["reports"]
1447 assert length(response["reports"]) == 1
1448 assert closed_report["id"] == second_report_id
1450 assert response["total"] == 1
1454 |> get("/api/pleroma/admin/reports", %{
1455 "state" => "resolved"
1457 |> json_response(:ok)
1459 assert Enum.empty?(response["reports"])
1460 assert response["total"] == 0
1463 test "returns 403 when requested by a non-admin" do
1464 user = insert(:user)
1465 token = insert(:oauth_token, user: user)
1469 |> assign(:user, user)
1470 |> assign(:token, token)
1471 |> get("/api/pleroma/admin/reports")
1473 assert json_response(conn, :forbidden) ==
1474 %{"error" => "User is not an admin or OAuth admin scope is not granted."}
1477 test "returns 403 when requested by anonymous" do
1478 conn = get(build_conn(), "/api/pleroma/admin/reports")
1480 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1484 describe "GET /api/pleroma/admin/config" do
1485 setup do: clear_config(:configurable_from_database, true)
1487 test "when configuration from database is off", %{conn: conn} do
1488 Config.put(:configurable_from_database, false)
1489 conn = get(conn, "/api/pleroma/admin/config")
1491 assert json_response(conn, 400) ==
1493 "error" => "To use this endpoint you need to enable configuration from database."
1497 test "with settings only in db", %{conn: conn} do
1498 config1 = insert(:config)
1499 config2 = insert(:config)
1501 conn = get(conn, "/api/pleroma/admin/config", %{"only_db" => true})
1506 "group" => ":pleroma",
1511 "group" => ":pleroma",
1516 } = json_response(conn, 200)
1518 assert key1 == config1.key
1519 assert key2 == config2.key
1522 test "db is added to settings that are in db", %{conn: conn} do
1523 _config = insert(:config, key: ":instance", value: ConfigDB.to_binary(name: "Some name"))
1525 %{"configs" => configs} =
1527 |> get("/api/pleroma/admin/config")
1528 |> json_response(200)
1531 Enum.filter(configs, fn %{"group" => group, "key" => key} ->
1532 group == ":pleroma" and key == ":instance"
1535 assert instance_config["db"] == [":name"]
1538 test "merged default setting with db settings", %{conn: conn} do
1539 config1 = insert(:config)
1540 config2 = insert(:config)
1544 value: ConfigDB.to_binary(k1: :v1, k2: :v2)
1547 %{"configs" => configs} =
1549 |> get("/api/pleroma/admin/config")
1550 |> json_response(200)
1552 assert length(configs) > 3
1555 Enum.filter(configs, fn %{"group" => group, "key" => key} ->
1556 group == ":pleroma" and key in [config1.key, config2.key, config3.key]
1559 assert length(received_configs) == 3
1563 |> ConfigDB.from_binary()
1565 |> ConfigDB.convert()
1567 Enum.each(received_configs, fn %{"value" => value, "db" => db} ->
1568 assert db in [[config1.key], [config2.key], db_keys]
1571 ConfigDB.from_binary_with_convert(config1.value),
1572 ConfigDB.from_binary_with_convert(config2.value),
1573 ConfigDB.from_binary_with_convert(config3.value)
1578 test "subkeys with full update right merge", %{conn: conn} do
1582 value: ConfigDB.to_binary(groups: [a: 1, b: 2], key: [a: 1])
1588 value: ConfigDB.to_binary(mascots: [a: 1, b: 2], key: [a: 1])
1591 %{"configs" => configs} =
1593 |> get("/api/pleroma/admin/config")
1594 |> json_response(200)
1597 Enum.filter(configs, fn %{"group" => group, "key" => key} ->
1598 group == ":pleroma" and key in [config1.key, config2.key]
1601 emoji = Enum.find(vals, fn %{"key" => key} -> key == ":emoji" end)
1602 assets = Enum.find(vals, fn %{"key" => key} -> key == ":assets" end)
1604 emoji_val = ConfigDB.transform_with_out_binary(emoji["value"])
1605 assets_val = ConfigDB.transform_with_out_binary(assets["value"])
1607 assert emoji_val[:groups] == [a: 1, b: 2]
1608 assert assets_val[:mascots] == [a: 1, b: 2]
1612 test "POST /api/pleroma/admin/config error", %{conn: conn} do
1613 conn = post(conn, "/api/pleroma/admin/config", %{"configs" => []})
1615 assert json_response(conn, 400) ==
1616 %{"error" => "To use this endpoint you need to enable configuration from database."}
1619 describe "POST /api/pleroma/admin/config" do
1621 http = Application.get_env(:pleroma, :http)
1624 Application.delete_env(:pleroma, :key1)
1625 Application.delete_env(:pleroma, :key2)
1626 Application.delete_env(:pleroma, :key3)
1627 Application.delete_env(:pleroma, :key4)
1628 Application.delete_env(:pleroma, :keyaa1)
1629 Application.delete_env(:pleroma, :keyaa2)
1630 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1631 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1632 Application.put_env(:pleroma, :http, http)
1633 Application.put_env(:tesla, :adapter, Tesla.Mock)
1634 Restarter.Pleroma.refresh()
1638 setup do: clear_config(:configurable_from_database, true)
1640 @tag capture_log: true
1641 test "create new config setting in db", %{conn: conn} do
1642 ueberauth = Application.get_env(:ueberauth, Ueberauth)
1643 on_exit(fn -> Application.put_env(:ueberauth, Ueberauth, ueberauth) end)
1646 post(conn, "/api/pleroma/admin/config", %{
1648 %{group: ":pleroma", key: ":key1", value: "value1"},
1650 group: ":ueberauth",
1652 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
1658 ":nested_1" => "nested_value1",
1660 %{":nested_22" => "nested_value222"},
1661 %{":nested_33" => %{":nested_44" => "nested_444"}}
1669 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1670 %{"nested_4" => true}
1676 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
1681 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1686 assert json_response(conn, 200) == %{
1689 "group" => ":pleroma",
1691 "value" => "value1",
1695 "group" => ":ueberauth",
1696 "key" => "Ueberauth",
1697 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}],
1698 "db" => [":consumer_secret"]
1701 "group" => ":pleroma",
1704 ":nested_1" => "nested_value1",
1706 %{":nested_22" => "nested_value222"},
1707 %{":nested_33" => %{":nested_44" => "nested_444"}}
1713 "group" => ":pleroma",
1716 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1717 %{"nested_4" => true}
1722 "group" => ":pleroma",
1724 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"},
1730 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]},
1736 assert Application.get_env(:pleroma, :key1) == "value1"
1738 assert Application.get_env(:pleroma, :key2) == %{
1739 nested_1: "nested_value1",
1741 %{nested_22: "nested_value222"},
1742 %{nested_33: %{nested_44: "nested_444"}}
1746 assert Application.get_env(:pleroma, :key3) == [
1747 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
1748 %{"nested_4" => true}
1751 assert Application.get_env(:pleroma, :key4) == %{
1752 "endpoint" => "https://example.com",
1756 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
1759 test "save configs setting without explicit key", %{conn: conn} do
1760 level = Application.get_env(:quack, :level)
1761 meta = Application.get_env(:quack, :meta)
1762 webhook_url = Application.get_env(:quack, :webhook_url)
1765 Application.put_env(:quack, :level, level)
1766 Application.put_env(:quack, :meta, meta)
1767 Application.put_env(:quack, :webhook_url, webhook_url)
1771 post(conn, "/api/pleroma/admin/config", %{
1785 key: ":webhook_url",
1786 value: "https://hooks.slack.com/services/KEY"
1791 assert json_response(conn, 200) == %{
1794 "group" => ":quack",
1800 "group" => ":quack",
1802 "value" => [":none"],
1806 "group" => ":quack",
1807 "key" => ":webhook_url",
1808 "value" => "https://hooks.slack.com/services/KEY",
1809 "db" => [":webhook_url"]
1814 assert Application.get_env(:quack, :level) == :info
1815 assert Application.get_env(:quack, :meta) == [:none]
1816 assert Application.get_env(:quack, :webhook_url) == "https://hooks.slack.com/services/KEY"
1819 test "saving config with partial update", %{conn: conn} do
1820 config = insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2))
1823 post(conn, "/api/pleroma/admin/config", %{
1825 %{group: config.group, key: config.key, value: [%{"tuple" => [":key3", 3]}]}
1829 assert json_response(conn, 200) == %{
1832 "group" => ":pleroma",
1835 %{"tuple" => [":key1", 1]},
1836 %{"tuple" => [":key2", 2]},
1837 %{"tuple" => [":key3", 3]}
1839 "db" => [":key1", ":key2", ":key3"]
1845 test "saving config which need pleroma reboot", %{conn: conn} do
1846 chat = Config.get(:chat)
1847 on_exit(fn -> Config.put(:chat, chat) end)
1851 "/api/pleroma/admin/config",
1854 %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]}
1858 |> json_response(200) == %{
1861 "db" => [":enabled"],
1862 "group" => ":pleroma",
1864 "value" => [%{"tuple" => [":enabled", true]}]
1867 "need_reboot" => true
1872 |> get("/api/pleroma/admin/config")
1873 |> json_response(200)
1875 assert configs["need_reboot"]
1878 assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
1879 end) =~ "pleroma restarted"
1883 |> get("/api/pleroma/admin/config")
1884 |> json_response(200)
1886 assert configs["need_reboot"] == false
1889 test "update setting which need reboot, don't change reboot flag until reboot", %{conn: conn} do
1890 chat = Config.get(:chat)
1891 on_exit(fn -> Config.put(:chat, chat) end)
1895 "/api/pleroma/admin/config",
1898 %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]}
1902 |> json_response(200) == %{
1905 "db" => [":enabled"],
1906 "group" => ":pleroma",
1908 "value" => [%{"tuple" => [":enabled", true]}]
1911 "need_reboot" => true
1914 assert post(conn, "/api/pleroma/admin/config", %{
1916 %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
1919 |> json_response(200) == %{
1922 "group" => ":pleroma",
1925 %{"tuple" => [":key3", 3]}
1930 "need_reboot" => true
1934 assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
1935 end) =~ "pleroma restarted"
1939 |> get("/api/pleroma/admin/config")
1940 |> json_response(200)
1942 assert configs["need_reboot"] == false
1945 test "saving config with nested merge", %{conn: conn} do
1947 insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: [k1: 1, k2: 2]))
1950 post(conn, "/api/pleroma/admin/config", %{
1953 group: config.group,
1956 %{"tuple" => [":key3", 3]},
1961 %{"tuple" => [":k2", 1]},
1962 %{"tuple" => [":k3", 3]}
1971 assert json_response(conn, 200) == %{
1974 "group" => ":pleroma",
1977 %{"tuple" => [":key1", 1]},
1978 %{"tuple" => [":key3", 3]},
1983 %{"tuple" => [":k1", 1]},
1984 %{"tuple" => [":k2", 1]},
1985 %{"tuple" => [":k3", 3]}
1990 "db" => [":key1", ":key3", ":key2"]
1996 test "saving special atoms", %{conn: conn} do
1998 post(conn, "/api/pleroma/admin/config", %{
2001 "group" => ":pleroma",
2007 [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
2015 assert json_response(conn, 200) == %{
2018 "group" => ":pleroma",
2024 [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
2028 "db" => [":ssl_options"]
2033 assert Application.get_env(:pleroma, :key1) == [
2034 ssl_options: [versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]]
2038 test "saving full setting if value is in full_key_update list", %{conn: conn} do
2039 backends = Application.get_env(:logger, :backends)
2040 on_exit(fn -> Application.put_env(:logger, :backends, backends) end)
2046 value: :erlang.term_to_binary([])
2049 Pleroma.Config.TransferTask.load_and_update_env([], false)
2051 assert Application.get_env(:logger, :backends) == []
2054 post(conn, "/api/pleroma/admin/config", %{
2057 group: config.group,
2064 assert json_response(conn, 200) == %{
2067 "group" => ":logger",
2068 "key" => ":backends",
2072 "db" => [":backends"]
2077 assert Application.get_env(:logger, :backends) == [
2082 test "saving full setting if value is not keyword", %{conn: conn} do
2087 value: :erlang.term_to_binary(Tesla.Adapter.Hackey)
2091 post(conn, "/api/pleroma/admin/config", %{
2093 %{group: config.group, key: config.key, value: "Tesla.Adapter.Httpc"}
2097 assert json_response(conn, 200) == %{
2100 "group" => ":tesla",
2101 "key" => ":adapter",
2102 "value" => "Tesla.Adapter.Httpc",
2103 "db" => [":adapter"]
2109 test "update config setting & delete with fallback to default value", %{
2114 ueberauth = Application.get_env(:ueberauth, Ueberauth)
2115 config1 = insert(:config, key: ":keyaa1")
2116 config2 = insert(:config, key: ":keyaa2")
2120 group: ":ueberauth",
2125 post(conn, "/api/pleroma/admin/config", %{
2127 %{group: config1.group, key: config1.key, value: "another_value"},
2128 %{group: config2.group, key: config2.key, value: "another_value"}
2132 assert json_response(conn, 200) == %{
2135 "group" => ":pleroma",
2136 "key" => config1.key,
2137 "value" => "another_value",
2141 "group" => ":pleroma",
2142 "key" => config2.key,
2143 "value" => "another_value",
2149 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
2150 assert Application.get_env(:pleroma, :keyaa2) == "another_value"
2151 assert Application.get_env(:ueberauth, Ueberauth) == ConfigDB.from_binary(config3.value)
2155 |> assign(:user, admin)
2156 |> assign(:token, token)
2157 |> post("/api/pleroma/admin/config", %{
2159 %{group: config2.group, key: config2.key, delete: true},
2161 group: ":ueberauth",
2168 assert json_response(conn, 200) == %{
2172 assert Application.get_env(:ueberauth, Ueberauth) == ueberauth
2173 refute Keyword.has_key?(Application.get_all_env(:pleroma), :keyaa2)
2176 test "common config example", %{conn: conn} do
2178 post(conn, "/api/pleroma/admin/config", %{
2181 "group" => ":pleroma",
2182 "key" => "Pleroma.Captcha.NotReal",
2184 %{"tuple" => [":enabled", false]},
2185 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2186 %{"tuple" => [":seconds_valid", 60]},
2187 %{"tuple" => [":path", ""]},
2188 %{"tuple" => [":key1", nil]},
2189 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2190 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
2191 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2192 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2193 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},
2194 %{"tuple" => [":name", "Pleroma"]}
2200 assert Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"
2202 assert json_response(conn, 200) == %{
2205 "group" => ":pleroma",
2206 "key" => "Pleroma.Captcha.NotReal",
2208 %{"tuple" => [":enabled", false]},
2209 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2210 %{"tuple" => [":seconds_valid", 60]},
2211 %{"tuple" => [":path", ""]},
2212 %{"tuple" => [":key1", nil]},
2213 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2214 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2215 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2216 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2217 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]},
2218 %{"tuple" => [":name", "Pleroma"]}
2238 test "tuples with more than two values", %{conn: conn} do
2240 post(conn, "/api/pleroma/admin/config", %{
2243 "group" => ":pleroma",
2244 "key" => "Pleroma.Web.Endpoint.NotReal",
2260 "/api/v1/streaming",
2261 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2268 "Phoenix.Endpoint.CowboyWebSocket",
2271 "Phoenix.Transports.WebSocket",
2274 "Pleroma.Web.Endpoint",
2275 "Pleroma.Web.UserSocket",
2286 "Phoenix.Endpoint.Cowboy2Handler",
2287 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2304 assert json_response(conn, 200) == %{
2307 "group" => ":pleroma",
2308 "key" => "Pleroma.Web.Endpoint.NotReal",
2324 "/api/v1/streaming",
2325 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2332 "Phoenix.Endpoint.CowboyWebSocket",
2335 "Phoenix.Transports.WebSocket",
2338 "Pleroma.Web.Endpoint",
2339 "Pleroma.Web.UserSocket",
2350 "Phoenix.Endpoint.Cowboy2Handler",
2351 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2370 test "settings with nesting map", %{conn: conn} do
2372 post(conn, "/api/pleroma/admin/config", %{
2375 "group" => ":pleroma",
2378 %{"tuple" => [":key2", "some_val"]},
2383 ":max_options" => 20,
2384 ":max_option_chars" => 200,
2385 ":min_expiration" => 0,
2386 ":max_expiration" => 31_536_000,
2388 ":max_options" => 20,
2389 ":max_option_chars" => 200,
2390 ":min_expiration" => 0,
2391 ":max_expiration" => 31_536_000
2401 assert json_response(conn, 200) ==
2405 "group" => ":pleroma",
2408 %{"tuple" => [":key2", "some_val"]},
2413 ":max_expiration" => 31_536_000,
2414 ":max_option_chars" => 200,
2415 ":max_options" => 20,
2416 ":min_expiration" => 0,
2418 ":max_expiration" => 31_536_000,
2419 ":max_option_chars" => 200,
2420 ":max_options" => 20,
2421 ":min_expiration" => 0
2427 "db" => [":key2", ":key3"]
2433 test "value as map", %{conn: conn} do
2435 post(conn, "/api/pleroma/admin/config", %{
2438 "group" => ":pleroma",
2440 "value" => %{"key" => "some_val"}
2445 assert json_response(conn, 200) ==
2449 "group" => ":pleroma",
2451 "value" => %{"key" => "some_val"},
2458 test "queues key as atom", %{conn: conn} do
2460 post(conn, "/api/pleroma/admin/config", %{
2466 %{"tuple" => [":federator_incoming", 50]},
2467 %{"tuple" => [":federator_outgoing", 50]},
2468 %{"tuple" => [":web_push", 50]},
2469 %{"tuple" => [":mailer", 10]},
2470 %{"tuple" => [":transmogrifier", 20]},
2471 %{"tuple" => [":scheduled_activities", 10]},
2472 %{"tuple" => [":background", 5]}
2478 assert json_response(conn, 200) == %{
2484 %{"tuple" => [":federator_incoming", 50]},
2485 %{"tuple" => [":federator_outgoing", 50]},
2486 %{"tuple" => [":web_push", 50]},
2487 %{"tuple" => [":mailer", 10]},
2488 %{"tuple" => [":transmogrifier", 20]},
2489 %{"tuple" => [":scheduled_activities", 10]},
2490 %{"tuple" => [":background", 5]}
2493 ":federator_incoming",
2494 ":federator_outgoing",
2498 ":scheduled_activities",
2506 test "delete part of settings by atom subkeys", %{conn: conn} do
2510 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2514 post(conn, "/api/pleroma/admin/config", %{
2517 group: config.group,
2519 subkeys: [":subkey1", ":subkey3"],
2525 assert json_response(conn, 200) == %{
2528 "group" => ":pleroma",
2530 "value" => [%{"tuple" => [":subkey2", "val2"]}],
2531 "db" => [":subkey2"]
2537 test "proxy tuple localhost", %{conn: conn} do
2539 post(conn, "/api/pleroma/admin/config", %{
2545 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]}
2554 "group" => ":pleroma",
2560 } = json_response(conn, 200)
2562 assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]} in value
2563 assert ":proxy_url" in db
2566 test "proxy tuple domain", %{conn: conn} do
2568 post(conn, "/api/pleroma/admin/config", %{
2574 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]}
2583 "group" => ":pleroma",
2589 } = json_response(conn, 200)
2591 assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]} in value
2592 assert ":proxy_url" in db
2595 test "proxy tuple ip", %{conn: conn} do
2597 post(conn, "/api/pleroma/admin/config", %{
2603 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]}
2612 "group" => ":pleroma",
2618 } = json_response(conn, 200)
2620 assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]} in value
2621 assert ":proxy_url" in db
2624 @tag capture_log: true
2625 test "doesn't set keys not in the whitelist", %{conn: conn} do
2626 clear_config(:database_config_whitelist, [
2629 {:pleroma, Pleroma.Captcha.NotReal},
2633 post(conn, "/api/pleroma/admin/config", %{
2635 %{group: ":pleroma", key: ":key1", value: "value1"},
2636 %{group: ":pleroma", key: ":key2", value: "value2"},
2637 %{group: ":pleroma", key: ":key3", value: "value3"},
2638 %{group: ":pleroma", key: "Pleroma.Web.Endpoint.NotReal", value: "value4"},
2639 %{group: ":pleroma", key: "Pleroma.Captcha.NotReal", value: "value5"},
2640 %{group: ":not_real", key: ":anything", value: "value6"}
2644 assert Application.get_env(:pleroma, :key1) == "value1"
2645 assert Application.get_env(:pleroma, :key2) == "value2"
2646 assert Application.get_env(:pleroma, :key3) == nil
2647 assert Application.get_env(:pleroma, Pleroma.Web.Endpoint.NotReal) == nil
2648 assert Application.get_env(:pleroma, Pleroma.Captcha.NotReal) == "value5"
2649 assert Application.get_env(:not_real, :anything) == "value6"
2653 describe "GET /api/pleroma/admin/restart" do
2654 setup do: clear_config(:configurable_from_database, true)
2656 test "pleroma restarts", %{conn: conn} do
2658 assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
2659 end) =~ "pleroma restarted"
2661 refute Restarter.Pleroma.need_reboot?()
2665 test "need_reboot flag", %{conn: conn} do
2667 |> get("/api/pleroma/admin/need_reboot")
2668 |> json_response(200) == %{"need_reboot" => false}
2670 Restarter.Pleroma.need_reboot()
2673 |> get("/api/pleroma/admin/need_reboot")
2674 |> json_response(200) == %{"need_reboot" => true}
2676 on_exit(fn -> Restarter.Pleroma.refresh() end)
2679 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2681 user = insert(:user)
2683 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2684 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2685 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2687 insert(:note_activity, user: user, published: date1)
2688 insert(:note_activity, user: user, published: date2)
2689 insert(:note_activity, user: user, published: date3)
2694 test "renders user's statuses", %{conn: conn, user: user} do
2695 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2697 assert json_response(conn, 200) |> length() == 3
2700 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2701 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2703 assert json_response(conn, 200) |> length() == 2
2706 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2707 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
2709 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
2711 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2713 assert json_response(conn, 200) |> length() == 4
2716 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2717 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
2719 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
2721 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2723 assert json_response(conn, 200) |> length() == 5
2726 test "excludes reblogs by default", %{conn: conn, user: user} do
2727 other_user = insert(:user)
2728 {:ok, activity} = CommonAPI.post(user, %{status: "."})
2729 {:ok, %Activity{}} = CommonAPI.repeat(activity.id, other_user)
2731 conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses")
2732 assert json_response(conn_res, 200) |> length() == 0
2735 get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true")
2737 assert json_response(conn_res, 200) |> length() == 1
2741 describe "GET /api/pleroma/admin/moderation_log" do
2743 moderator = insert(:user, is_moderator: true)
2745 %{moderator: moderator}
2748 test "returns the log", %{conn: conn, admin: admin} do
2749 Repo.insert(%ModerationLog{
2753 "nickname" => admin.nickname,
2756 action: "relay_follow",
2757 target: "https://example.org/relay"
2759 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2762 Repo.insert(%ModerationLog{
2766 "nickname" => admin.nickname,
2769 action: "relay_unfollow",
2770 target: "https://example.org/relay"
2772 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2775 conn = get(conn, "/api/pleroma/admin/moderation_log")
2777 response = json_response(conn, 200)
2778 [first_entry, second_entry] = response["items"]
2780 assert response["total"] == 2
2781 assert first_entry["data"]["action"] == "relay_unfollow"
2783 assert first_entry["message"] ==
2784 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2786 assert second_entry["data"]["action"] == "relay_follow"
2788 assert second_entry["message"] ==
2789 "@#{admin.nickname} followed relay: https://example.org/relay"
2792 test "returns the log with pagination", %{conn: conn, admin: admin} do
2793 Repo.insert(%ModerationLog{
2797 "nickname" => admin.nickname,
2800 action: "relay_follow",
2801 target: "https://example.org/relay"
2803 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2806 Repo.insert(%ModerationLog{
2810 "nickname" => admin.nickname,
2813 action: "relay_unfollow",
2814 target: "https://example.org/relay"
2816 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2819 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2821 response1 = json_response(conn1, 200)
2822 [first_entry] = response1["items"]
2824 assert response1["total"] == 2
2825 assert response1["items"] |> length() == 1
2826 assert first_entry["data"]["action"] == "relay_unfollow"
2828 assert first_entry["message"] ==
2829 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2831 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2833 response2 = json_response(conn2, 200)
2834 [second_entry] = response2["items"]
2836 assert response2["total"] == 2
2837 assert response2["items"] |> length() == 1
2838 assert second_entry["data"]["action"] == "relay_follow"
2840 assert second_entry["message"] ==
2841 "@#{admin.nickname} followed relay: https://example.org/relay"
2844 test "filters log by date", %{conn: conn, admin: admin} do
2845 first_date = "2017-08-15T15:47:06Z"
2846 second_date = "2017-08-20T15:47:06Z"
2848 Repo.insert(%ModerationLog{
2852 "nickname" => admin.nickname,
2855 action: "relay_follow",
2856 target: "https://example.org/relay"
2858 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2861 Repo.insert(%ModerationLog{
2865 "nickname" => admin.nickname,
2868 action: "relay_unfollow",
2869 target: "https://example.org/relay"
2871 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2877 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2880 response1 = json_response(conn1, 200)
2881 [first_entry] = response1["items"]
2883 assert response1["total"] == 1
2884 assert first_entry["data"]["action"] == "relay_unfollow"
2886 assert first_entry["message"] ==
2887 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2890 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2891 Repo.insert(%ModerationLog{
2895 "nickname" => admin.nickname,
2898 action: "relay_follow",
2899 target: "https://example.org/relay"
2903 Repo.insert(%ModerationLog{
2906 "id" => moderator.id,
2907 "nickname" => moderator.nickname,
2910 action: "relay_unfollow",
2911 target: "https://example.org/relay"
2915 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2917 response1 = json_response(conn1, 200)
2918 [first_entry] = response1["items"]
2920 assert response1["total"] == 1
2921 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2924 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2925 ModerationLog.insert_log(%{
2927 action: "relay_follow",
2928 target: "https://example.org/relay"
2931 ModerationLog.insert_log(%{
2933 action: "relay_unfollow",
2934 target: "https://example.org/relay"
2937 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2939 response1 = json_response(conn1, 200)
2940 [first_entry] = response1["items"]
2942 assert response1["total"] == 1
2944 assert get_in(first_entry, ["data", "message"]) ==
2945 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2949 describe "GET /users/:nickname/credentials" do
2950 test "gets the user credentials", %{conn: conn} do
2951 user = insert(:user)
2952 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
2954 response = assert json_response(conn, 200)
2955 assert response["email"] == user.email
2958 test "returns 403 if requested by a non-admin" do
2959 user = insert(:user)
2963 |> assign(:user, user)
2964 |> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
2966 assert json_response(conn, :forbidden)
2970 describe "PATCH /users/:nickname/credentials" do
2971 test "changes password and email", %{conn: conn, admin: admin} do
2972 user = insert(:user)
2973 assert user.password_reset_pending == false
2976 patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
2977 "password" => "new_password",
2978 "email" => "new_email@example.com",
2979 "name" => "new_name"
2982 assert json_response(conn, 200) == %{"status" => "success"}
2984 ObanHelpers.perform_all()
2986 updated_user = User.get_by_id(user.id)
2988 assert updated_user.email == "new_email@example.com"
2989 assert updated_user.name == "new_name"
2990 assert updated_user.password_hash != user.password_hash
2991 assert updated_user.password_reset_pending == true
2993 [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
2995 assert ModerationLog.get_log_entry_message(log_entry1) ==
2996 "@#{admin.nickname} updated users: @#{user.nickname}"
2998 assert ModerationLog.get_log_entry_message(log_entry2) ==
2999 "@#{admin.nickname} forced password reset for users: @#{user.nickname}"
3002 test "returns 403 if requested by a non-admin" do
3003 user = insert(:user)
3007 |> assign(:user, user)
3008 |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
3009 "password" => "new_password",
3010 "email" => "new_email@example.com",
3011 "name" => "new_name"
3014 assert json_response(conn, :forbidden)
3018 describe "PATCH /users/:nickname/force_password_reset" do
3019 test "sets password_reset_pending to true", %{conn: conn} do
3020 user = insert(:user)
3021 assert user.password_reset_pending == false
3024 patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
3026 assert json_response(conn, 204) == ""
3028 ObanHelpers.perform_all()
3030 assert User.get_by_id(user.id).password_reset_pending == true
3034 describe "relays" do
3035 test "POST /relay", %{conn: conn, admin: admin} do
3037 post(conn, "/api/pleroma/admin/relay", %{
3038 relay_url: "http://mastodon.example.org/users/admin"
3041 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
3043 log_entry = Repo.one(ModerationLog)
3045 assert ModerationLog.get_log_entry_message(log_entry) ==
3046 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
3049 test "GET /relay", %{conn: conn} do
3050 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
3052 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
3053 |> Enum.each(fn ap_id ->
3054 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
3055 User.follow(relay_user, user)
3058 conn = get(conn, "/api/pleroma/admin/relay")
3060 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
3063 test "DELETE /relay", %{conn: conn, admin: admin} do
3064 post(conn, "/api/pleroma/admin/relay", %{
3065 relay_url: "http://mastodon.example.org/users/admin"
3069 delete(conn, "/api/pleroma/admin/relay", %{
3070 relay_url: "http://mastodon.example.org/users/admin"
3073 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
3075 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
3077 assert ModerationLog.get_log_entry_message(log_entry_one) ==
3078 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
3080 assert ModerationLog.get_log_entry_message(log_entry_two) ==
3081 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
3085 describe "instances" do
3086 test "GET /instances/:instance/statuses", %{conn: conn} do
3087 user = insert(:user, local: false, nickname: "archaeme@archae.me")
3088 user2 = insert(:user, local: false, nickname: "test@test.com")
3089 insert_pair(:note_activity, user: user)
3090 activity = insert(:note_activity, user: user2)
3092 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
3094 response = json_response(ret_conn, 200)
3096 assert length(response) == 2
3098 ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses")
3100 response = json_response(ret_conn, 200)
3102 assert length(response) == 1
3104 ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses")
3106 response = json_response(ret_conn, 200)
3108 assert Enum.empty?(response)
3110 CommonAPI.repeat(activity.id, user)
3112 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
3113 response = json_response(ret_conn, 200)
3114 assert length(response) == 2
3116 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
3117 response = json_response(ret_conn, 200)
3118 assert length(response) == 3
3122 describe "PATCH /confirm_email" do
3123 test "it confirms emails of two users", %{conn: conn, admin: admin} do
3124 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
3126 assert first_user.confirmation_pending == true
3127 assert second_user.confirmation_pending == true
3130 patch(conn, "/api/pleroma/admin/users/confirm_email", %{
3132 first_user.nickname,
3133 second_user.nickname
3137 assert ret_conn.status == 200
3139 assert first_user.confirmation_pending == true
3140 assert second_user.confirmation_pending == true
3142 log_entry = Repo.one(ModerationLog)
3144 assert ModerationLog.get_log_entry_message(log_entry) ==
3145 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
3146 second_user.nickname
3151 describe "PATCH /resend_confirmation_email" do
3152 test "it resend emails for two users", %{conn: conn, admin: admin} do
3153 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
3156 patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{
3158 first_user.nickname,
3159 second_user.nickname
3163 assert ret_conn.status == 200
3165 log_entry = Repo.one(ModerationLog)
3167 assert ModerationLog.get_log_entry_message(log_entry) ==
3168 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
3169 second_user.nickname
3174 describe "POST /reports/:id/notes" do
3175 setup %{conn: conn, admin: admin} do
3176 [reporter, target_user] = insert_pair(:user)
3177 activity = insert(:note_activity, user: target_user)
3179 {:ok, %{id: report_id}} =
3180 CommonAPI.report(reporter, %{
3181 account_id: target_user.id,
3182 comment: "I feel offended",
3183 status_ids: [activity.id]
3186 post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
3187 content: "this is disgusting!"
3190 post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
3191 content: "this is disgusting2!"
3196 report_id: report_id
3200 test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
3201 [note, _] = Repo.all(ReportNote)
3204 activity_id: ^report_id,
3205 content: "this is disgusting!",
3210 test "it returns reports with notes", %{conn: conn, admin: admin} do
3211 conn = get(conn, "/api/pleroma/admin/reports")
3213 response = json_response(conn, 200)
3214 notes = hd(response["reports"])["notes"]
3217 assert note["user"]["nickname"] == admin.nickname
3218 assert note["content"] == "this is disgusting!"
3219 assert note["created_at"]
3220 assert response["total"] == 1
3223 test "it deletes the note", %{conn: conn, report_id: report_id} do
3224 assert ReportNote |> Repo.all() |> length() == 2
3226 [note, _] = Repo.all(ReportNote)
3228 delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
3230 assert ReportNote |> Repo.all() |> length() == 1
3234 describe "GET /api/pleroma/admin/config/descriptions" do
3235 test "structure", %{conn: conn} do
3236 admin = insert(:user, is_admin: true)
3239 assign(conn, :user, admin)
3240 |> get("/api/pleroma/admin/config/descriptions")
3242 assert [child | _others] = json_response(conn, 200)
3244 assert child["children"]
3246 assert String.starts_with?(child["group"], ":")
3247 assert child["description"]
3250 test "filters by database configuration whitelist", %{conn: conn} do
3251 clear_config(:database_config_whitelist, [
3252 {:pleroma, :instance},
3253 {:pleroma, :activitypub},
3254 {:pleroma, Pleroma.Upload},
3258 admin = insert(:user, is_admin: true)
3261 assign(conn, :user, admin)
3262 |> get("/api/pleroma/admin/config/descriptions")
3264 children = json_response(conn, 200)
3266 assert length(children) == 4
3268 assert Enum.count(children, fn c -> c["group"] == ":pleroma" end) == 3
3270 instance = Enum.find(children, fn c -> c["key"] == ":instance" end)
3271 assert instance["children"]
3273 activitypub = Enum.find(children, fn c -> c["key"] == ":activitypub" end)
3274 assert activitypub["children"]
3276 web_endpoint = Enum.find(children, fn c -> c["key"] == "Pleroma.Upload" end)
3277 assert web_endpoint["children"]
3279 esshd = Enum.find(children, fn c -> c["group"] == ":esshd" end)
3280 assert esshd["children"]
3284 describe "/api/pleroma/admin/stats" do
3285 test "status visibility count", %{conn: conn} do
3286 admin = insert(:user, is_admin: true)
3287 user = insert(:user)
3288 CommonAPI.post(user, %{visibility: "public", status: "hey"})
3289 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
3290 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
3294 |> assign(:user, admin)
3295 |> get("/api/pleroma/admin/stats")
3296 |> json_response(200)
3298 assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
3299 response["status_visibility"]
3303 describe "POST /api/pleroma/admin/oauth_app" do
3304 test "errors", %{conn: conn} do
3305 response = conn |> post("/api/pleroma/admin/oauth_app", %{}) |> json_response(200)
3307 assert response == %{"name" => "can't be blank", "redirect_uris" => "can't be blank"}
3310 test "success", %{conn: conn} do
3311 base_url = Web.base_url()
3312 app_name = "Trusted app"
3316 |> post("/api/pleroma/admin/oauth_app", %{
3318 redirect_uris: base_url
3320 |> json_response(200)
3324 "client_secret" => _,
3325 "name" => ^app_name,
3326 "redirect_uri" => ^base_url,
3331 test "with trusted", %{conn: conn} do
3332 base_url = Web.base_url()
3333 app_name = "Trusted app"
3337 |> post("/api/pleroma/admin/oauth_app", %{
3339 redirect_uris: base_url,
3342 |> json_response(200)
3346 "client_secret" => _,
3347 "name" => ^app_name,
3348 "redirect_uri" => ^base_url,
3354 describe "GET /api/pleroma/admin/oauth_app" do
3356 app = insert(:oauth_app)
3360 test "list", %{conn: conn} do
3363 |> get("/api/pleroma/admin/oauth_app")
3364 |> json_response(200)
3366 assert %{"apps" => apps, "count" => count, "page_size" => _} = response
3368 assert length(apps) == count
3371 test "with page size", %{conn: conn} do
3377 |> get("/api/pleroma/admin/oauth_app", %{page_size: to_string(page_size)})
3378 |> json_response(200)
3380 assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response
3382 assert length(apps) == page_size
3385 test "search by client name", %{conn: conn, app: app} do
3388 |> get("/api/pleroma/admin/oauth_app", %{name: app.client_name})
3389 |> json_response(200)
3391 assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
3393 assert returned["client_id"] == app.client_id
3394 assert returned["name"] == app.client_name
3397 test "search by client id", %{conn: conn, app: app} do
3400 |> get("/api/pleroma/admin/oauth_app", %{client_id: app.client_id})
3401 |> json_response(200)
3403 assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
3405 assert returned["client_id"] == app.client_id
3406 assert returned["name"] == app.client_name
3409 test "only trusted", %{conn: conn} do
3410 app = insert(:oauth_app, trusted: true)
3414 |> get("/api/pleroma/admin/oauth_app", %{trusted: true})
3415 |> json_response(200)
3417 assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
3419 assert returned["client_id"] == app.client_id
3420 assert returned["name"] == app.client_name
3424 describe "DELETE /api/pleroma/admin/oauth_app/:id" do
3425 test "with id", %{conn: conn} do
3426 app = insert(:oauth_app)
3430 |> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id))
3431 |> json_response(:no_content)
3433 assert response == ""
3436 test "with non existance id", %{conn: conn} do
3439 |> delete("/api/pleroma/admin/oauth_app/0")
3440 |> json_response(:bad_request)
3442 assert response == ""
3446 describe "PATCH /api/pleroma/admin/oauth_app/:id" do
3447 test "with id", %{conn: conn} do
3448 app = insert(:oauth_app)
3450 name = "another name"
3451 url = "https://example.com"
3454 website = "http://website.com"
3458 |> patch("/api/pleroma/admin/oauth_app/" <> to_string(app.id), %{
3465 |> json_response(200)
3469 "client_secret" => _,
3472 "redirect_uri" => ^url,
3474 "website" => ^website
3478 test "without id", %{conn: conn} do
3481 |> patch("/api/pleroma/admin/oauth_app/0")
3482 |> json_response(:bad_request)
3484 assert response == ""
3489 # Needed for testing
3490 defmodule Pleroma.Web.Endpoint.NotReal do
3493 defmodule Pleroma.Captcha.NotReal do