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.MastodonAPI.StatusView
20 alias Pleroma.Web.MediaProxy
21 import Pleroma.Factory
24 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
29 clear_config([:auth, :enforce_oauth_admin_scope_usage]) do
30 Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], false)
33 describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
34 clear_config([:auth, :enforce_oauth_admin_scope_usage]) do
35 Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], true)
38 test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope" do
40 admin = insert(:user, is_admin: true)
41 url = "/api/pleroma/admin/users/#{user.nickname}"
43 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
44 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
45 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
47 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
48 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
51 for good_token <- [good_token1, good_token2, good_token3] do
54 |> assign(:user, admin)
55 |> assign(:token, good_token)
58 assert json_response(conn, 200)
61 for good_token <- [good_token1, good_token2, good_token3] do
65 |> assign(:token, good_token)
68 assert json_response(conn, :forbidden)
71 for bad_token <- [bad_token1, bad_token2, bad_token3] do
74 |> assign(:user, admin)
75 |> assign(:token, bad_token)
78 assert json_response(conn, :forbidden)
83 describe "DELETE /api/pleroma/admin/users" do
85 admin = insert(:user, is_admin: true)
90 |> assign(:user, admin)
91 |> put_req_header("accept", "application/json")
92 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
94 log_entry = Repo.one(ModerationLog)
96 assert ModerationLog.get_log_entry_message(log_entry) ==
97 "@#{admin.nickname} deleted users: @#{user.nickname}"
99 assert json_response(conn, 200) == user.nickname
102 test "multiple users" do
103 admin = insert(:user, is_admin: true)
104 user_one = insert(:user)
105 user_two = insert(:user)
109 |> assign(:user, admin)
110 |> put_req_header("accept", "application/json")
111 |> delete("/api/pleroma/admin/users", %{
112 nicknames: [user_one.nickname, user_two.nickname]
115 log_entry = Repo.one(ModerationLog)
117 assert ModerationLog.get_log_entry_message(log_entry) ==
118 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
120 response = json_response(conn, 200)
121 assert response -- [user_one.nickname, user_two.nickname] == []
125 describe "/api/pleroma/admin/users" do
127 admin = insert(:user, is_admin: true)
131 |> assign(:user, admin)
132 |> put_req_header("accept", "application/json")
133 |> post("/api/pleroma/admin/users", %{
136 "nickname" => "lain",
137 "email" => "lain@example.org",
141 "nickname" => "lain2",
142 "email" => "lain2@example.org",
148 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
149 assert response == ["success", "success"]
151 log_entry = Repo.one(ModerationLog)
153 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
156 test "Cannot create user with existing email" do
157 admin = insert(:user, is_admin: true)
162 |> assign(:user, admin)
163 |> put_req_header("accept", "application/json")
164 |> post("/api/pleroma/admin/users", %{
167 "nickname" => "lain",
168 "email" => user.email,
174 assert json_response(conn, 409) == [
178 "email" => user.email,
181 "error" => "email has already been taken",
187 test "Cannot create user with existing nickname" do
188 admin = insert(:user, is_admin: true)
193 |> assign(:user, admin)
194 |> put_req_header("accept", "application/json")
195 |> post("/api/pleroma/admin/users", %{
198 "nickname" => user.nickname,
199 "email" => "someuser@plerama.social",
205 assert json_response(conn, 409) == [
209 "email" => "someuser@plerama.social",
210 "nickname" => user.nickname
212 "error" => "nickname has already been taken",
218 test "Multiple user creation works in transaction" do
219 admin = insert(:user, is_admin: true)
224 |> assign(:user, admin)
225 |> put_req_header("accept", "application/json")
226 |> post("/api/pleroma/admin/users", %{
229 "nickname" => "newuser",
230 "email" => "newuser@pleroma.social",
234 "nickname" => "lain",
235 "email" => user.email,
241 assert json_response(conn, 409) == [
245 "email" => user.email,
248 "error" => "email has already been taken",
254 "email" => "newuser@pleroma.social",
255 "nickname" => "newuser"
262 assert User.get_by_nickname("newuser") === nil
266 describe "/api/pleroma/admin/users/:nickname" do
267 test "Show", %{conn: conn} do
268 admin = insert(:user, is_admin: true)
273 |> assign(:user, admin)
274 |> get("/api/pleroma/admin/users/#{user.nickname}")
277 "deactivated" => false,
278 "id" => to_string(user.id),
280 "nickname" => user.nickname,
281 "roles" => %{"admin" => false, "moderator" => false},
283 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
284 "display_name" => HTML.strip_tags(user.name || user.nickname),
285 "confirmation_pending" => false
288 assert expected == json_response(conn, 200)
291 test "when the user doesn't exist", %{conn: conn} do
292 admin = insert(:user, is_admin: true)
297 |> assign(:user, admin)
298 |> get("/api/pleroma/admin/users/#{user.nickname}")
300 assert "Not found" == json_response(conn, 404)
304 describe "/api/pleroma/admin/users/follow" do
305 test "allows to force-follow another user" do
306 admin = insert(:user, is_admin: true)
308 follower = insert(:user)
311 |> assign(:user, admin)
312 |> put_req_header("accept", "application/json")
313 |> post("/api/pleroma/admin/users/follow", %{
314 "follower" => follower.nickname,
315 "followed" => user.nickname
318 user = User.get_cached_by_id(user.id)
319 follower = User.get_cached_by_id(follower.id)
321 assert User.following?(follower, user)
323 log_entry = Repo.one(ModerationLog)
325 assert ModerationLog.get_log_entry_message(log_entry) ==
326 "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
330 describe "/api/pleroma/admin/users/unfollow" do
331 test "allows to force-unfollow another user" do
332 admin = insert(:user, is_admin: true)
334 follower = insert(:user)
336 User.follow(follower, user)
339 |> assign(:user, admin)
340 |> put_req_header("accept", "application/json")
341 |> post("/api/pleroma/admin/users/unfollow", %{
342 "follower" => follower.nickname,
343 "followed" => user.nickname
346 user = User.get_cached_by_id(user.id)
347 follower = User.get_cached_by_id(follower.id)
349 refute User.following?(follower, user)
351 log_entry = Repo.one(ModerationLog)
353 assert ModerationLog.get_log_entry_message(log_entry) ==
354 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
358 describe "PUT /api/pleroma/admin/users/tag" do
360 admin = insert(:user, is_admin: true)
361 user1 = insert(:user, %{tags: ["x"]})
362 user2 = insert(:user, %{tags: ["y"]})
363 user3 = insert(:user, %{tags: ["unchanged"]})
367 |> assign(:user, admin)
368 |> put_req_header("accept", "application/json")
370 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
372 }&tags[]=foo&tags[]=bar"
375 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
378 test "it appends specified tags to users with specified nicknames", %{
384 assert json_response(conn, :no_content)
385 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
386 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
388 log_entry = Repo.one(ModerationLog)
391 [user1.nickname, user2.nickname]
392 |> Enum.map(&"@#{&1}")
395 tags = ["foo", "bar"] |> Enum.join(", ")
397 assert ModerationLog.get_log_entry_message(log_entry) ==
398 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
401 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
402 assert json_response(conn, :no_content)
403 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
407 describe "DELETE /api/pleroma/admin/users/tag" do
409 admin = insert(:user, is_admin: true)
410 user1 = insert(:user, %{tags: ["x"]})
411 user2 = insert(:user, %{tags: ["y", "z"]})
412 user3 = insert(:user, %{tags: ["unchanged"]})
416 |> assign(:user, admin)
417 |> put_req_header("accept", "application/json")
419 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
424 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
427 test "it removes specified tags from users with specified nicknames", %{
433 assert json_response(conn, :no_content)
434 assert User.get_cached_by_id(user1.id).tags == []
435 assert User.get_cached_by_id(user2.id).tags == ["y"]
437 log_entry = Repo.one(ModerationLog)
440 [user1.nickname, user2.nickname]
441 |> Enum.map(&"@#{&1}")
444 tags = ["x", "z"] |> Enum.join(", ")
446 assert ModerationLog.get_log_entry_message(log_entry) ==
447 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
450 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
451 assert json_response(conn, :no_content)
452 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
456 describe "/api/pleroma/admin/users/:nickname/permission_group" do
457 test "GET is giving user_info" do
458 admin = insert(:user, is_admin: true)
462 |> assign(:user, admin)
463 |> put_req_header("accept", "application/json")
464 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
466 assert json_response(conn, 200) == %{
468 "is_moderator" => false
472 test "/:right POST, can add to a permission group" do
473 admin = insert(:user, is_admin: true)
478 |> assign(:user, admin)
479 |> put_req_header("accept", "application/json")
480 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
482 assert json_response(conn, 200) == %{
486 log_entry = Repo.one(ModerationLog)
488 assert ModerationLog.get_log_entry_message(log_entry) ==
489 "@#{admin.nickname} made @#{user.nickname} admin"
492 test "/:right POST, can add to a permission group (multiple)" do
493 admin = insert(:user, is_admin: true)
494 user_one = insert(:user)
495 user_two = insert(:user)
499 |> assign(:user, admin)
500 |> put_req_header("accept", "application/json")
501 |> post("/api/pleroma/admin/users/permission_group/admin", %{
502 nicknames: [user_one.nickname, user_two.nickname]
505 assert json_response(conn, 200) == %{
509 log_entry = Repo.one(ModerationLog)
511 assert ModerationLog.get_log_entry_message(log_entry) ==
512 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
515 test "/:right DELETE, can remove from a permission group" do
516 admin = insert(:user, is_admin: true)
517 user = insert(:user, is_admin: true)
521 |> assign(:user, admin)
522 |> put_req_header("accept", "application/json")
523 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
525 assert json_response(conn, 200) == %{
529 log_entry = Repo.one(ModerationLog)
531 assert ModerationLog.get_log_entry_message(log_entry) ==
532 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
535 test "/:right DELETE, can remove from a permission group (multiple)" do
536 admin = insert(:user, is_admin: true)
537 user_one = insert(:user, is_admin: true)
538 user_two = insert(:user, is_admin: true)
542 |> assign(:user, admin)
543 |> put_req_header("accept", "application/json")
544 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
545 nicknames: [user_one.nickname, user_two.nickname]
548 assert json_response(conn, 200) == %{
552 log_entry = Repo.one(ModerationLog)
554 assert ModerationLog.get_log_entry_message(log_entry) ==
555 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
561 describe "POST /api/pleroma/admin/email_invite, with valid config" do
563 [user: insert(:user, is_admin: true)]
566 clear_config([:instance, :registrations_open]) do
567 Pleroma.Config.put([:instance, :registrations_open], false)
570 clear_config([:instance, :invites_enabled]) do
571 Pleroma.Config.put([:instance, :invites_enabled], true)
574 test "sends invitation and returns 204", %{conn: conn, user: user} do
575 recipient_email = "foo@bar.com"
576 recipient_name = "J. D."
580 |> assign(:user, user)
582 "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
585 assert json_response(conn, :no_content)
587 token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken))
589 refute token_record.used
591 notify_email = Pleroma.Config.get([:instance, :notify_email])
592 instance_name = Pleroma.Config.get([:instance, :name])
595 Pleroma.Emails.UserEmail.user_invitation_email(
602 Swoosh.TestAssertions.assert_email_sent(
603 from: {instance_name, notify_email},
604 to: {recipient_name, recipient_email},
605 html_body: email.html_body
609 test "it returns 403 if requested by a non-admin", %{conn: conn} do
610 non_admin_user = insert(:user)
614 |> assign(:user, non_admin_user)
615 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
617 assert json_response(conn, :forbidden)
621 describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
623 [user: insert(:user, is_admin: true)]
626 clear_config([:instance, :registrations_open])
627 clear_config([:instance, :invites_enabled])
629 test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
630 Pleroma.Config.put([:instance, :registrations_open], false)
631 Pleroma.Config.put([:instance, :invites_enabled], false)
635 |> assign(:user, user)
636 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
638 assert json_response(conn, :internal_server_error)
641 test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
642 Pleroma.Config.put([:instance, :registrations_open], true)
643 Pleroma.Config.put([:instance, :invites_enabled], true)
647 |> assign(:user, user)
648 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
650 assert json_response(conn, :internal_server_error)
654 test "/api/pleroma/admin/users/:nickname/password_reset" do
655 admin = insert(:user, is_admin: true)
660 |> assign(:user, admin)
661 |> put_req_header("accept", "application/json")
662 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
664 resp = json_response(conn, 200)
666 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
669 describe "GET /api/pleroma/admin/users" do
671 admin = insert(:user, is_admin: true)
675 |> assign(:user, admin)
677 {:ok, conn: conn, admin: admin}
680 test "renders users array for the first page", %{conn: conn, admin: admin} do
681 user = insert(:user, local: false, tags: ["foo", "bar"])
682 conn = get(conn, "/api/pleroma/admin/users?page=1")
687 "deactivated" => admin.deactivated,
689 "nickname" => admin.nickname,
690 "roles" => %{"admin" => true, "moderator" => false},
693 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
694 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
695 "confirmation_pending" => false
698 "deactivated" => user.deactivated,
700 "nickname" => user.nickname,
701 "roles" => %{"admin" => false, "moderator" => false},
703 "tags" => ["foo", "bar"],
704 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
705 "display_name" => HTML.strip_tags(user.name || user.nickname),
706 "confirmation_pending" => false
709 |> Enum.sort_by(& &1["nickname"])
711 assert json_response(conn, 200) == %{
718 test "renders empty array for the second page", %{conn: conn} do
721 conn = get(conn, "/api/pleroma/admin/users?page=2")
723 assert json_response(conn, 200) == %{
730 test "regular search", %{conn: conn} do
731 user = insert(:user, nickname: "bob")
733 conn = get(conn, "/api/pleroma/admin/users?query=bo")
735 assert json_response(conn, 200) == %{
740 "deactivated" => user.deactivated,
742 "nickname" => user.nickname,
743 "roles" => %{"admin" => false, "moderator" => false},
746 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
747 "display_name" => HTML.strip_tags(user.name || user.nickname),
748 "confirmation_pending" => false
754 test "search by domain", %{conn: conn} do
755 user = insert(:user, nickname: "nickname@domain.com")
758 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
760 assert json_response(conn, 200) == %{
765 "deactivated" => user.deactivated,
767 "nickname" => user.nickname,
768 "roles" => %{"admin" => false, "moderator" => false},
771 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
772 "display_name" => HTML.strip_tags(user.name || user.nickname),
773 "confirmation_pending" => false
779 test "search by full nickname", %{conn: conn} do
780 user = insert(:user, nickname: "nickname@domain.com")
783 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
785 assert json_response(conn, 200) == %{
790 "deactivated" => user.deactivated,
792 "nickname" => user.nickname,
793 "roles" => %{"admin" => false, "moderator" => false},
796 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
797 "display_name" => HTML.strip_tags(user.name || user.nickname),
798 "confirmation_pending" => false
804 test "search by display name", %{conn: conn} do
805 user = insert(:user, name: "Display name")
808 conn = get(conn, "/api/pleroma/admin/users?name=display")
810 assert json_response(conn, 200) == %{
815 "deactivated" => user.deactivated,
817 "nickname" => user.nickname,
818 "roles" => %{"admin" => false, "moderator" => false},
821 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
822 "display_name" => HTML.strip_tags(user.name || user.nickname),
823 "confirmation_pending" => false
829 test "search by email", %{conn: conn} do
830 user = insert(:user, email: "email@example.com")
833 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
835 assert json_response(conn, 200) == %{
840 "deactivated" => user.deactivated,
842 "nickname" => user.nickname,
843 "roles" => %{"admin" => false, "moderator" => false},
846 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
847 "display_name" => HTML.strip_tags(user.name || user.nickname),
848 "confirmation_pending" => false
854 test "regular search with page size", %{conn: conn} do
855 user = insert(:user, nickname: "aalice")
856 user2 = insert(:user, nickname: "alice")
858 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
860 assert json_response(conn1, 200) == %{
865 "deactivated" => user.deactivated,
867 "nickname" => user.nickname,
868 "roles" => %{"admin" => false, "moderator" => false},
871 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
872 "display_name" => HTML.strip_tags(user.name || user.nickname),
873 "confirmation_pending" => false
878 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
880 assert json_response(conn2, 200) == %{
885 "deactivated" => user2.deactivated,
887 "nickname" => user2.nickname,
888 "roles" => %{"admin" => false, "moderator" => false},
891 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
892 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
893 "confirmation_pending" => false
899 test "only local users" do
900 admin = insert(:user, is_admin: true, nickname: "john")
901 user = insert(:user, nickname: "bob")
903 insert(:user, nickname: "bobb", local: false)
907 |> assign(:user, admin)
908 |> get("/api/pleroma/admin/users?query=bo&filters=local")
910 assert json_response(conn, 200) == %{
915 "deactivated" => user.deactivated,
917 "nickname" => user.nickname,
918 "roles" => %{"admin" => false, "moderator" => false},
921 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
922 "display_name" => HTML.strip_tags(user.name || user.nickname),
923 "confirmation_pending" => false
929 test "only local users with no query", %{admin: old_admin} do
930 admin = insert(:user, is_admin: true, nickname: "john")
931 user = insert(:user, nickname: "bob")
933 insert(:user, nickname: "bobb", local: false)
937 |> assign(:user, admin)
938 |> get("/api/pleroma/admin/users?filters=local")
943 "deactivated" => user.deactivated,
945 "nickname" => user.nickname,
946 "roles" => %{"admin" => false, "moderator" => false},
949 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
950 "display_name" => HTML.strip_tags(user.name || user.nickname),
951 "confirmation_pending" => false
954 "deactivated" => admin.deactivated,
956 "nickname" => admin.nickname,
957 "roles" => %{"admin" => true, "moderator" => false},
960 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
961 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
962 "confirmation_pending" => false
965 "deactivated" => false,
966 "id" => old_admin.id,
968 "nickname" => old_admin.nickname,
969 "roles" => %{"admin" => true, "moderator" => false},
971 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
972 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
973 "confirmation_pending" => false
976 |> Enum.sort_by(& &1["nickname"])
978 assert json_response(conn, 200) == %{
985 test "load only admins", %{conn: conn, admin: admin} do
986 second_admin = insert(:user, is_admin: true)
990 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
995 "deactivated" => false,
997 "nickname" => admin.nickname,
998 "roles" => %{"admin" => true, "moderator" => false},
999 "local" => admin.local,
1001 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1002 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
1003 "confirmation_pending" => false
1006 "deactivated" => false,
1007 "id" => second_admin.id,
1008 "nickname" => second_admin.nickname,
1009 "roles" => %{"admin" => true, "moderator" => false},
1010 "local" => second_admin.local,
1012 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
1013 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
1014 "confirmation_pending" => false
1017 |> Enum.sort_by(& &1["nickname"])
1019 assert json_response(conn, 200) == %{
1026 test "load only moderators", %{conn: conn} do
1027 moderator = insert(:user, is_moderator: true)
1031 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
1033 assert json_response(conn, 200) == %{
1038 "deactivated" => false,
1039 "id" => moderator.id,
1040 "nickname" => moderator.nickname,
1041 "roles" => %{"admin" => false, "moderator" => true},
1042 "local" => moderator.local,
1044 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
1045 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
1046 "confirmation_pending" => false
1052 test "load users with tags list", %{conn: conn} do
1053 user1 = insert(:user, tags: ["first"])
1054 user2 = insert(:user, tags: ["second"])
1058 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
1063 "deactivated" => false,
1065 "nickname" => user1.nickname,
1066 "roles" => %{"admin" => false, "moderator" => false},
1067 "local" => user1.local,
1068 "tags" => ["first"],
1069 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
1070 "display_name" => HTML.strip_tags(user1.name || user1.nickname),
1071 "confirmation_pending" => false
1074 "deactivated" => false,
1076 "nickname" => user2.nickname,
1077 "roles" => %{"admin" => false, "moderator" => false},
1078 "local" => user2.local,
1079 "tags" => ["second"],
1080 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1081 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
1082 "confirmation_pending" => false
1085 |> Enum.sort_by(& &1["nickname"])
1087 assert json_response(conn, 200) == %{
1094 test "it works with multiple filters" do
1095 admin = insert(:user, nickname: "john", is_admin: true)
1096 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1098 insert(:user, nickname: "ken", local: true, deactivated: true)
1099 insert(:user, nickname: "bobb", local: false, deactivated: false)
1103 |> assign(:user, admin)
1104 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1106 assert json_response(conn, 200) == %{
1111 "deactivated" => user.deactivated,
1113 "nickname" => user.nickname,
1114 "roles" => %{"admin" => false, "moderator" => false},
1115 "local" => user.local,
1117 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1118 "display_name" => HTML.strip_tags(user.name || user.nickname),
1119 "confirmation_pending" => false
1125 test "it omits relay user", %{admin: admin} do
1126 assert %User{} = Relay.get_actor()
1130 |> assign(:user, admin)
1131 |> get("/api/pleroma/admin/users")
1133 assert json_response(conn, 200) == %{
1138 "deactivated" => admin.deactivated,
1140 "nickname" => admin.nickname,
1141 "roles" => %{"admin" => true, "moderator" => false},
1144 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1145 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
1146 "confirmation_pending" => false
1153 test "PATCH /api/pleroma/admin/users/activate" do
1154 admin = insert(:user, is_admin: true)
1155 user_one = insert(:user, deactivated: true)
1156 user_two = insert(:user, deactivated: true)
1160 |> assign(:user, admin)
1162 "/api/pleroma/admin/users/activate",
1163 %{nicknames: [user_one.nickname, user_two.nickname]}
1166 response = json_response(conn, 200)
1167 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1169 log_entry = Repo.one(ModerationLog)
1171 assert ModerationLog.get_log_entry_message(log_entry) ==
1172 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1175 test "PATCH /api/pleroma/admin/users/deactivate" do
1176 admin = insert(:user, is_admin: true)
1177 user_one = insert(:user, deactivated: false)
1178 user_two = insert(:user, deactivated: false)
1182 |> assign(:user, admin)
1184 "/api/pleroma/admin/users/deactivate",
1185 %{nicknames: [user_one.nickname, user_two.nickname]}
1188 response = json_response(conn, 200)
1189 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1191 log_entry = Repo.one(ModerationLog)
1193 assert ModerationLog.get_log_entry_message(log_entry) ==
1194 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1197 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
1198 admin = insert(:user, is_admin: true)
1199 user = insert(:user)
1203 |> assign(:user, admin)
1204 |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1206 assert json_response(conn, 200) ==
1208 "deactivated" => !user.deactivated,
1210 "nickname" => user.nickname,
1211 "roles" => %{"admin" => false, "moderator" => false},
1214 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1215 "display_name" => HTML.strip_tags(user.name || user.nickname),
1216 "confirmation_pending" => false
1219 log_entry = Repo.one(ModerationLog)
1221 assert ModerationLog.get_log_entry_message(log_entry) ==
1222 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1225 describe "POST /api/pleroma/admin/users/invite_token" do
1227 admin = insert(:user, is_admin: true)
1231 |> assign(:user, admin)
1236 test "without options", %{conn: conn} do
1237 conn = post(conn, "/api/pleroma/admin/users/invite_token")
1239 invite_json = json_response(conn, 200)
1240 invite = UserInviteToken.find_by_token!(invite_json["token"])
1242 refute invite.expires_at
1243 refute invite.max_use
1244 assert invite.invite_type == "one_time"
1247 test "with expires_at", %{conn: conn} do
1249 post(conn, "/api/pleroma/admin/users/invite_token", %{
1250 "expires_at" => Date.to_string(Date.utc_today())
1253 invite_json = json_response(conn, 200)
1254 invite = UserInviteToken.find_by_token!(invite_json["token"])
1257 assert invite.expires_at == Date.utc_today()
1258 refute invite.max_use
1259 assert invite.invite_type == "date_limited"
1262 test "with max_use", %{conn: conn} do
1263 conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
1265 invite_json = json_response(conn, 200)
1266 invite = UserInviteToken.find_by_token!(invite_json["token"])
1268 refute invite.expires_at
1269 assert invite.max_use == 150
1270 assert invite.invite_type == "reusable"
1273 test "with max use and expires_at", %{conn: conn} do
1275 post(conn, "/api/pleroma/admin/users/invite_token", %{
1277 "expires_at" => Date.to_string(Date.utc_today())
1280 invite_json = json_response(conn, 200)
1281 invite = UserInviteToken.find_by_token!(invite_json["token"])
1283 assert invite.expires_at == Date.utc_today()
1284 assert invite.max_use == 150
1285 assert invite.invite_type == "reusable_date_limited"
1289 describe "GET /api/pleroma/admin/users/invites" do
1291 admin = insert(:user, is_admin: true)
1295 |> assign(:user, admin)
1300 test "no invites", %{conn: conn} do
1301 conn = get(conn, "/api/pleroma/admin/users/invites")
1303 assert json_response(conn, 200) == %{"invites" => []}
1306 test "with invite", %{conn: conn} do
1307 {:ok, invite} = UserInviteToken.create_invite()
1309 conn = get(conn, "/api/pleroma/admin/users/invites")
1311 assert json_response(conn, 200) == %{
1314 "expires_at" => nil,
1316 "invite_type" => "one_time",
1318 "token" => invite.token,
1327 describe "POST /api/pleroma/admin/users/revoke_invite" do
1328 test "with token" do
1329 admin = insert(:user, is_admin: true)
1330 {:ok, invite} = UserInviteToken.create_invite()
1334 |> assign(:user, admin)
1335 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
1337 assert json_response(conn, 200) == %{
1338 "expires_at" => nil,
1340 "invite_type" => "one_time",
1342 "token" => invite.token,
1348 test "with invalid token" do
1349 admin = insert(:user, is_admin: true)
1353 |> assign(:user, admin)
1354 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
1356 assert json_response(conn, :not_found) == "Not found"
1360 describe "GET /api/pleroma/admin/reports/:id" do
1361 setup %{conn: conn} do
1362 admin = insert(:user, is_admin: true)
1364 %{conn: assign(conn, :user, admin)}
1367 test "returns report by its id", %{conn: conn} do
1368 [reporter, target_user] = insert_pair(:user)
1369 activity = insert(:note_activity, user: target_user)
1371 {:ok, %{id: report_id}} =
1372 CommonAPI.report(reporter, %{
1373 "account_id" => target_user.id,
1374 "comment" => "I feel offended",
1375 "status_ids" => [activity.id]
1380 |> get("/api/pleroma/admin/reports/#{report_id}")
1381 |> json_response(:ok)
1383 assert response["id"] == report_id
1386 test "returns 404 when report id is invalid", %{conn: conn} do
1387 conn = get(conn, "/api/pleroma/admin/reports/test")
1389 assert json_response(conn, :not_found) == "Not found"
1393 describe "PATCH /api/pleroma/admin/reports" do
1394 setup %{conn: conn} do
1395 admin = insert(:user, is_admin: true)
1396 [reporter, target_user] = insert_pair(:user)
1397 activity = insert(:note_activity, user: target_user)
1399 {:ok, %{id: report_id}} =
1400 CommonAPI.report(reporter, %{
1401 "account_id" => target_user.id,
1402 "comment" => "I feel offended",
1403 "status_ids" => [activity.id]
1406 {:ok, %{id: second_report_id}} =
1407 CommonAPI.report(reporter, %{
1408 "account_id" => target_user.id,
1409 "comment" => "I feel very offended",
1410 "status_ids" => [activity.id]
1414 conn: assign(conn, :user, admin),
1417 second_report_id: second_report_id
1421 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1423 |> patch("/api/pleroma/admin/reports", %{
1425 %{"state" => "resolved", "id" => id}
1428 |> json_response(:no_content)
1430 activity = Activity.get_by_id(id)
1431 assert activity.data["state"] == "resolved"
1433 log_entry = Repo.one(ModerationLog)
1435 assert ModerationLog.get_log_entry_message(log_entry) ==
1436 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1439 test "closes report", %{conn: conn, id: id, admin: admin} do
1441 |> patch("/api/pleroma/admin/reports", %{
1443 %{"state" => "closed", "id" => id}
1446 |> json_response(:no_content)
1448 activity = Activity.get_by_id(id)
1449 assert activity.data["state"] == "closed"
1451 log_entry = Repo.one(ModerationLog)
1453 assert ModerationLog.get_log_entry_message(log_entry) ==
1454 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1457 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1460 |> patch("/api/pleroma/admin/reports", %{
1462 %{"state" => "test", "id" => id}
1466 assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
1469 test "returns 404 when report is not exist", %{conn: conn} do
1472 |> patch("/api/pleroma/admin/reports", %{
1474 %{"state" => "closed", "id" => "test"}
1478 assert hd(json_response(conn, :bad_request))["error"] == "not_found"
1481 test "updates state of multiple reports", %{
1485 second_report_id: second_report_id
1488 |> patch("/api/pleroma/admin/reports", %{
1490 %{"state" => "resolved", "id" => id},
1491 %{"state" => "closed", "id" => second_report_id}
1494 |> json_response(:no_content)
1496 activity = Activity.get_by_id(id)
1497 second_activity = Activity.get_by_id(second_report_id)
1498 assert activity.data["state"] == "resolved"
1499 assert second_activity.data["state"] == "closed"
1501 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
1503 assert ModerationLog.get_log_entry_message(first_log_entry) ==
1504 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1506 assert ModerationLog.get_log_entry_message(second_log_entry) ==
1507 "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
1511 describe "GET /api/pleroma/admin/reports" do
1512 setup %{conn: conn} do
1513 admin = insert(:user, is_admin: true)
1515 %{conn: assign(conn, :user, admin)}
1518 test "returns empty response when no reports created", %{conn: conn} do
1521 |> get("/api/pleroma/admin/reports")
1522 |> json_response(:ok)
1524 assert Enum.empty?(response["reports"])
1525 assert response["total"] == 0
1528 test "returns reports", %{conn: conn} do
1529 [reporter, target_user] = insert_pair(:user)
1530 activity = insert(:note_activity, user: target_user)
1532 {:ok, %{id: report_id}} =
1533 CommonAPI.report(reporter, %{
1534 "account_id" => target_user.id,
1535 "comment" => "I feel offended",
1536 "status_ids" => [activity.id]
1541 |> get("/api/pleroma/admin/reports")
1542 |> json_response(:ok)
1544 [report] = response["reports"]
1546 assert length(response["reports"]) == 1
1547 assert report["id"] == report_id
1549 assert response["total"] == 1
1552 test "returns reports with specified state", %{conn: conn} do
1553 [reporter, target_user] = insert_pair(:user)
1554 activity = insert(:note_activity, user: target_user)
1556 {:ok, %{id: first_report_id}} =
1557 CommonAPI.report(reporter, %{
1558 "account_id" => target_user.id,
1559 "comment" => "I feel offended",
1560 "status_ids" => [activity.id]
1563 {:ok, %{id: second_report_id}} =
1564 CommonAPI.report(reporter, %{
1565 "account_id" => target_user.id,
1566 "comment" => "I don't like this user"
1569 CommonAPI.update_report_state(second_report_id, "closed")
1573 |> get("/api/pleroma/admin/reports", %{
1576 |> json_response(:ok)
1578 [open_report] = response["reports"]
1580 assert length(response["reports"]) == 1
1581 assert open_report["id"] == first_report_id
1583 assert response["total"] == 1
1587 |> get("/api/pleroma/admin/reports", %{
1590 |> json_response(:ok)
1592 [closed_report] = response["reports"]
1594 assert length(response["reports"]) == 1
1595 assert closed_report["id"] == second_report_id
1597 assert response["total"] == 1
1601 |> get("/api/pleroma/admin/reports", %{
1602 "state" => "resolved"
1604 |> json_response(:ok)
1606 assert Enum.empty?(response["reports"])
1607 assert response["total"] == 0
1610 test "returns 403 when requested by a non-admin" do
1611 user = insert(:user)
1615 |> assign(:user, user)
1616 |> get("/api/pleroma/admin/reports")
1618 assert json_response(conn, :forbidden) ==
1619 %{"error" => "User is not an admin or OAuth admin scope is not granted."}
1622 test "returns 403 when requested by anonymous" do
1625 |> get("/api/pleroma/admin/reports")
1627 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1631 describe "GET /api/pleroma/admin/grouped_reports" do
1632 setup %{conn: conn} do
1633 admin = insert(:user, is_admin: true)
1634 [reporter, target_user] = insert_pair(:user)
1636 date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
1637 date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
1638 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
1641 insert(:note_activity, user: target_user, data_attrs: %{"published" => date1})
1644 insert(:note_activity, user: target_user, data_attrs: %{"published" => date2})
1647 insert(:note_activity, user: target_user, data_attrs: %{"published" => date3})
1649 {:ok, first_report} =
1650 CommonAPI.report(reporter, %{
1651 "account_id" => target_user.id,
1652 "status_ids" => [first_status.id, second_status.id, third_status.id]
1655 {:ok, second_report} =
1656 CommonAPI.report(reporter, %{
1657 "account_id" => target_user.id,
1658 "status_ids" => [first_status.id, second_status.id]
1661 {:ok, third_report} =
1662 CommonAPI.report(reporter, %{
1663 "account_id" => target_user.id,
1664 "status_ids" => [first_status.id]
1668 conn: assign(conn, :user, admin),
1669 first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
1670 second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
1671 third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
1672 first_report: first_report,
1673 first_status_reports: [first_report, second_report, third_report],
1674 second_status_reports: [first_report, second_report],
1675 third_status_reports: [first_report],
1676 target_user: target_user,
1681 test "returns reports grouped by status", %{
1683 first_status: first_status,
1684 second_status: second_status,
1685 third_status: third_status,
1686 first_status_reports: first_status_reports,
1687 second_status_reports: second_status_reports,
1688 third_status_reports: third_status_reports,
1689 target_user: target_user,
1694 |> get("/api/pleroma/admin/grouped_reports")
1695 |> json_response(:ok)
1697 assert length(response["reports"]) == 3
1699 first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id))
1701 second_group = Enum.find(response["reports"], &(&1["status"]["id"] == second_status.id))
1703 third_group = Enum.find(response["reports"], &(&1["status"]["id"] == third_status.id))
1705 assert length(first_group["reports"]) == 3
1706 assert length(second_group["reports"]) == 2
1707 assert length(third_group["reports"]) == 1
1709 assert first_group["date"] ==
1710 Enum.max_by(first_status_reports, fn act ->
1711 NaiveDateTime.from_iso8601!(act.data["published"])
1712 end).data["published"]
1714 assert first_group["status"] ==
1716 stringify_keys(StatusView.render("show.json", %{activity: first_status})),
1721 assert(first_group["account"]["id"] == target_user.id)
1723 assert length(first_group["actors"]) == 1
1724 assert hd(first_group["actors"])["id"] == reporter.id
1726 assert Enum.map(first_group["reports"], & &1["id"]) --
1727 Enum.map(first_status_reports, & &1.id) == []
1729 assert second_group["date"] ==
1730 Enum.max_by(second_status_reports, fn act ->
1731 NaiveDateTime.from_iso8601!(act.data["published"])
1732 end).data["published"]
1734 assert second_group["status"] ==
1736 stringify_keys(StatusView.render("show.json", %{activity: second_status})),
1741 assert second_group["account"]["id"] == target_user.id
1743 assert length(second_group["actors"]) == 1
1744 assert hd(second_group["actors"])["id"] == reporter.id
1746 assert Enum.map(second_group["reports"], & &1["id"]) --
1747 Enum.map(second_status_reports, & &1.id) == []
1749 assert third_group["date"] ==
1750 Enum.max_by(third_status_reports, fn act ->
1751 NaiveDateTime.from_iso8601!(act.data["published"])
1752 end).data["published"]
1754 assert third_group["status"] ==
1756 stringify_keys(StatusView.render("show.json", %{activity: third_status})),
1761 assert third_group["account"]["id"] == target_user.id
1763 assert length(third_group["actors"]) == 1
1764 assert hd(third_group["actors"])["id"] == reporter.id
1766 assert Enum.map(third_group["reports"], & &1["id"]) --
1767 Enum.map(third_status_reports, & &1.id) == []
1770 test "reopened report renders status data", %{
1772 first_report: first_report,
1773 first_status: first_status
1775 {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
1779 |> get("/api/pleroma/admin/grouped_reports")
1780 |> json_response(:ok)
1782 first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id))
1784 assert first_group["status"] ==
1786 stringify_keys(StatusView.render("show.json", %{activity: first_status})),
1792 test "reopened report does not render status data if status has been deleted", %{
1794 first_report: first_report,
1795 first_status: first_status,
1796 target_user: target_user
1798 {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
1799 {:ok, _} = CommonAPI.delete(first_status.id, target_user)
1801 refute Activity.get_by_ap_id(first_status.id)
1805 |> get("/api/pleroma/admin/grouped_reports")
1806 |> json_response(:ok)
1808 assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["status"][
1812 assert length(Enum.filter(response["reports"], &(&1["status"]["deleted"] == false))) == 2
1815 test "account not empty if status was deleted", %{
1817 first_report: first_report,
1818 first_status: first_status,
1819 target_user: target_user
1821 {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
1822 {:ok, _} = CommonAPI.delete(first_status.id, target_user)
1824 refute Activity.get_by_ap_id(first_status.id)
1828 |> get("/api/pleroma/admin/grouped_reports")
1829 |> json_response(:ok)
1831 assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["account"]
1835 describe "PUT /api/pleroma/admin/statuses/:id" do
1836 setup %{conn: conn} do
1837 admin = insert(:user, is_admin: true)
1838 activity = insert(:note_activity)
1840 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1843 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1846 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1847 |> json_response(:ok)
1849 assert response["sensitive"]
1851 log_entry = Repo.one(ModerationLog)
1853 assert ModerationLog.get_log_entry_message(log_entry) ==
1854 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1858 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1859 |> json_response(:ok)
1861 refute response["sensitive"]
1864 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1867 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1868 |> json_response(:ok)
1870 assert response["visibility"] == "public"
1872 log_entry = Repo.one(ModerationLog)
1874 assert ModerationLog.get_log_entry_message(log_entry) ==
1875 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1879 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1880 |> json_response(:ok)
1882 assert response["visibility"] == "private"
1886 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1887 |> json_response(:ok)
1889 assert response["visibility"] == "unlisted"
1892 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1895 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1897 assert json_response(conn, :bad_request) == "Unsupported visibility"
1901 describe "DELETE /api/pleroma/admin/statuses/:id" do
1902 setup %{conn: conn} do
1903 admin = insert(:user, is_admin: true)
1904 activity = insert(:note_activity)
1906 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1909 test "deletes status", %{conn: conn, id: id, admin: admin} do
1911 |> delete("/api/pleroma/admin/statuses/#{id}")
1912 |> json_response(:ok)
1914 refute Activity.get_by_id(id)
1916 log_entry = Repo.one(ModerationLog)
1918 assert ModerationLog.get_log_entry_message(log_entry) ==
1919 "@#{admin.nickname} deleted status ##{id}"
1922 test "returns error when status is not exist", %{conn: conn} do
1925 |> delete("/api/pleroma/admin/statuses/test")
1927 assert json_response(conn, :bad_request) == "Could not delete"
1931 describe "GET /api/pleroma/admin/config" do
1932 clear_config([:instance, :dynamic_configuration]) do
1933 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1936 setup %{conn: conn} do
1937 admin = insert(:user, is_admin: true)
1939 %{conn: assign(conn, :user, admin)}
1942 test "when dynamic configuration is off", %{conn: conn} do
1943 initial = Pleroma.Config.get([:instance, :dynamic_configuration])
1944 Pleroma.Config.put([:instance, :dynamic_configuration], false)
1945 on_exit(fn -> Pleroma.Config.put([:instance, :dynamic_configuration], initial) end)
1946 conn = get(conn, "/api/pleroma/admin/config")
1948 assert json_response(conn, 400) ==
1949 "To use this endpoint you need to enable dynamic configuration."
1952 test "without any settings in db", %{conn: conn} do
1953 conn = get(conn, "/api/pleroma/admin/config")
1955 assert json_response(conn, 400) ==
1956 "To use dynamic configuration migrate your settings to database."
1959 test "with settings in db", %{conn: conn} do
1960 config1 = insert(:config)
1961 config2 = insert(:config)
1963 conn = get(conn, "/api/pleroma/admin/config")
1968 "group" => ":pleroma",
1977 } = json_response(conn, 200)
1979 assert key1 == config1.key
1980 assert key2 == config2.key
1984 test "POST /api/pleroma/admin/config error" do
1985 admin = insert(:user, is_admin: true)
1989 |> assign(:user, admin)
1990 |> post("/api/pleroma/admin/config", %{"configs" => []})
1992 assert json_response(conn, 400) ==
1993 "To use this endpoint you need to enable dynamic configuration."
1996 describe "POST /api/pleroma/admin/config" do
1997 setup %{conn: conn} do
1998 admin = insert(:user, is_admin: true)
2000 http = Application.get_env(:pleroma, :http)
2003 Application.delete_env(:pleroma, :key1)
2004 Application.delete_env(:pleroma, :key2)
2005 Application.delete_env(:pleroma, :key3)
2006 Application.delete_env(:pleroma, :key4)
2007 Application.delete_env(:pleroma, :keyaa1)
2008 Application.delete_env(:pleroma, :keyaa2)
2009 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
2010 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
2011 Application.put_env(:pleroma, :http, http)
2012 Application.put_env(:tesla, :adapter, Tesla.Mock)
2013 :ok = File.rm("config/test.exported_from_db.secret.exs")
2016 %{conn: assign(conn, :user, admin)}
2019 clear_config([:instance, :dynamic_configuration]) do
2020 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2023 @tag capture_log: true
2024 test "create new config setting in db", %{conn: conn} do
2026 post(conn, "/api/pleroma/admin/config", %{
2028 %{group: ":pleroma", key: ":key1", value: "value1"},
2030 group: ":ueberauth",
2031 key: "Ueberauth.Strategy.Twitter.OAuth",
2032 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
2038 ":nested_1" => "nested_value1",
2040 %{":nested_22" => "nested_value222"},
2041 %{":nested_33" => %{":nested_44" => "nested_444"}}
2049 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
2050 %{"nested_4" => true}
2056 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
2061 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
2066 assert json_response(conn, 200) == %{
2069 "group" => ":pleroma",
2074 "group" => ":ueberauth",
2075 "key" => "Ueberauth.Strategy.Twitter.OAuth",
2076 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
2079 "group" => ":pleroma",
2082 ":nested_1" => "nested_value1",
2084 %{":nested_22" => "nested_value222"},
2085 %{":nested_33" => %{":nested_44" => "nested_444"}}
2090 "group" => ":pleroma",
2093 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
2094 %{"nested_4" => true}
2098 "group" => ":pleroma",
2100 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
2105 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
2110 assert Application.get_env(:pleroma, :key1) == "value1"
2112 assert Application.get_env(:pleroma, :key2) == %{
2113 nested_1: "nested_value1",
2115 %{nested_22: "nested_value222"},
2116 %{nested_33: %{nested_44: "nested_444"}}
2120 assert Application.get_env(:pleroma, :key3) == [
2121 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
2122 %{"nested_4" => true}
2125 assert Application.get_env(:pleroma, :key4) == %{
2126 "endpoint" => "https://example.com",
2130 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
2133 test "save config setting without key", %{conn: conn} do
2134 level = Application.get_env(:quack, :level)
2135 meta = Application.get_env(:quack, :meta)
2136 webhook_url = Application.get_env(:quack, :webhook_url)
2139 Application.put_env(:quack, :level, level)
2140 Application.put_env(:quack, :meta, meta)
2141 Application.put_env(:quack, :webhook_url, webhook_url)
2145 post(conn, "/api/pleroma/admin/config", %{
2159 key: ":webhook_url",
2160 value: "https://hooks.slack.com/services/KEY"
2165 assert json_response(conn, 200) == %{
2167 %{"group" => ":quack", "key" => ":level", "value" => ":info"},
2168 %{"group" => ":quack", "key" => ":meta", "value" => [":none"]},
2170 "group" => ":quack",
2171 "key" => ":webhook_url",
2172 "value" => "https://hooks.slack.com/services/KEY"
2177 assert Application.get_env(:quack, :level) == :info
2178 assert Application.get_env(:quack, :meta) == [:none]
2179 assert Application.get_env(:quack, :webhook_url) == "https://hooks.slack.com/services/KEY"
2182 test "saving config with partial update", %{conn: conn} do
2183 config = insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2))
2186 post(conn, "/api/pleroma/admin/config", %{
2188 %{group: config.group, key: config.key, value: [%{"tuple" => [":key3", 3]}]}
2192 assert json_response(conn, 200) == %{
2195 "group" => ":pleroma",
2198 %{"tuple" => [":key1", 1]},
2199 %{"tuple" => [":key2", 2]},
2200 %{"tuple" => [":key3", 3]}
2207 test "saving config with nested merge", %{conn: conn} do
2209 insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: [k1: 1, k2: 2]))
2212 post(conn, "/api/pleroma/admin/config", %{
2215 group: config.group,
2218 %{"tuple" => [":key3", 3]},
2223 %{"tuple" => [":k2", 1]},
2224 %{"tuple" => [":k3", 3]}
2233 assert json_response(conn, 200) == %{
2236 "group" => ":pleroma",
2239 %{"tuple" => [":key1", 1]},
2240 %{"tuple" => [":key3", 3]},
2245 %{"tuple" => [":k1", 1]},
2246 %{"tuple" => [":k2", 1]},
2247 %{"tuple" => [":k3", 3]}
2257 test "saving special atoms", %{conn: conn} do
2259 post(conn, "/api/pleroma/admin/config", %{
2262 "group" => ":pleroma",
2268 [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
2276 assert json_response(conn, 200) == %{
2279 "group" => ":pleroma",
2285 [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
2293 assert Application.get_env(:pleroma, :key1) == [
2294 ssl_options: [versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]]
2298 test "saving full setting if value is in full_key_update list", %{conn: conn} do
2299 backends = Application.get_env(:logger, :backends)
2300 on_exit(fn -> Application.put_env(:logger, :backends, backends) end)
2306 value: :erlang.term_to_binary([])
2310 post(conn, "/api/pleroma/admin/config", %{
2313 group: config.group,
2315 value: [":console", %{"tuple" => ["ExSyslogger", ":ex_syslogger"]}]
2320 assert json_response(conn, 200) == %{
2323 "group" => ":logger",
2324 "key" => ":backends",
2327 %{"tuple" => ["ExSyslogger", ":ex_syslogger"]}
2333 assert Application.get_env(:logger, :backends) == [
2335 {ExSyslogger, :ex_syslogger}
2338 ExUnit.CaptureLog.capture_log(fn ->
2340 Logger.warn("Ooops...")
2344 test "saving full setting if value is not keyword", %{conn: conn} do
2349 value: :erlang.term_to_binary(Tesla.Adapter.Hackey)
2353 post(conn, "/api/pleroma/admin/config", %{
2355 %{group: config.group, key: config.key, value: "Tesla.Adapter.Httpc"}
2359 assert json_response(conn, 200) == %{
2362 "group" => ":tesla",
2363 "key" => ":adapter",
2364 "value" => "Tesla.Adapter.Httpc"
2370 test "update config setting & delete", %{conn: conn} do
2371 config1 = insert(:config, key: ":keyaa1")
2372 config2 = insert(:config, key: ":keyaa2")
2376 key: "Ueberauth.Strategy.Microsoft.OAuth"
2380 post(conn, "/api/pleroma/admin/config", %{
2382 %{group: config1.group, key: config1.key, value: "another_value"},
2383 %{group: config2.group, key: config2.key, delete: true},
2386 key: "Ueberauth.Strategy.Microsoft.OAuth",
2392 assert json_response(conn, 200) == %{
2395 "group" => ":pleroma",
2396 "key" => config1.key,
2397 "value" => "another_value"
2402 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
2403 refute Application.get_env(:pleroma, :keyaa2)
2406 test "common config example", %{conn: conn} do
2407 adapter = Application.get_env(:tesla, :adapter)
2408 on_exit(fn -> Application.put_env(:tesla, :adapter, adapter) end)
2411 post(conn, "/api/pleroma/admin/config", %{
2414 "group" => ":pleroma",
2415 "key" => "Pleroma.Captcha.NotReal",
2417 %{"tuple" => [":enabled", false]},
2418 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2419 %{"tuple" => [":seconds_valid", 60]},
2420 %{"tuple" => [":path", ""]},
2421 %{"tuple" => [":key1", nil]},
2422 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2423 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
2424 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2425 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2426 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},
2427 %{"tuple" => [":name", "Pleroma"]}
2430 %{"group" => ":tesla", "key" => ":adapter", "value" => "Tesla.Adapter.Httpc"}
2434 assert Application.get_env(:tesla, :adapter) == Tesla.Adapter.Httpc
2435 assert Pleroma.Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"
2437 assert json_response(conn, 200) == %{
2440 "group" => ":pleroma",
2441 "key" => "Pleroma.Captcha.NotReal",
2443 %{"tuple" => [":enabled", false]},
2444 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2445 %{"tuple" => [":seconds_valid", 60]},
2446 %{"tuple" => [":path", ""]},
2447 %{"tuple" => [":key1", nil]},
2448 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2449 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2450 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2451 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2452 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]},
2453 %{"tuple" => [":name", "Pleroma"]}
2456 %{"group" => ":tesla", "key" => ":adapter", "value" => "Tesla.Adapter.Httpc"}
2461 test "tuples with more than two values", %{conn: conn} do
2463 post(conn, "/api/pleroma/admin/config", %{
2466 "group" => ":pleroma",
2467 "key" => "Pleroma.Web.Endpoint.NotReal",
2483 "/api/v1/streaming",
2484 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2491 "Phoenix.Endpoint.CowboyWebSocket",
2494 "Phoenix.Transports.WebSocket",
2497 "Pleroma.Web.Endpoint",
2498 "Pleroma.Web.UserSocket",
2509 "Phoenix.Endpoint.Cowboy2Handler",
2510 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2527 assert json_response(conn, 200) == %{
2530 "group" => ":pleroma",
2531 "key" => "Pleroma.Web.Endpoint.NotReal",
2547 "/api/v1/streaming",
2548 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2555 "Phoenix.Endpoint.CowboyWebSocket",
2558 "Phoenix.Transports.WebSocket",
2561 "Pleroma.Web.Endpoint",
2562 "Pleroma.Web.UserSocket",
2573 "Phoenix.Endpoint.Cowboy2Handler",
2574 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2592 test "settings with nesting map", %{conn: conn} do
2594 post(conn, "/api/pleroma/admin/config", %{
2597 "group" => ":pleroma",
2600 %{"tuple" => [":key2", "some_val"]},
2605 ":max_options" => 20,
2606 ":max_option_chars" => 200,
2607 ":min_expiration" => 0,
2608 ":max_expiration" => 31_536_000,
2610 ":max_options" => 20,
2611 ":max_option_chars" => 200,
2612 ":min_expiration" => 0,
2613 ":max_expiration" => 31_536_000
2623 assert json_response(conn, 200) ==
2627 "group" => ":pleroma",
2630 %{"tuple" => [":key2", "some_val"]},
2635 ":max_expiration" => 31_536_000,
2636 ":max_option_chars" => 200,
2637 ":max_options" => 20,
2638 ":min_expiration" => 0,
2640 ":max_expiration" => 31_536_000,
2641 ":max_option_chars" => 200,
2642 ":max_options" => 20,
2643 ":min_expiration" => 0
2654 test "value as map", %{conn: conn} do
2656 post(conn, "/api/pleroma/admin/config", %{
2659 "group" => ":pleroma",
2661 "value" => %{"key" => "some_val"}
2666 assert json_response(conn, 200) ==
2670 "group" => ":pleroma",
2672 "value" => %{"key" => "some_val"}
2678 test "dispatch setting", %{conn: conn} do
2680 post(conn, "/api/pleroma/admin/config", %{
2683 "group" => ":pleroma",
2684 "key" => "Pleroma.Web.Endpoint.NotReal",
2690 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2691 %{"tuple" => [":dispatch", ["{:_,
2693 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2694 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2695 {Phoenix.Transports.WebSocket,
2696 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2697 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2708 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2709 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2710 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2711 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2713 assert json_response(conn, 200) == %{
2716 "group" => ":pleroma",
2717 "key" => "Pleroma.Web.Endpoint.NotReal",
2723 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2741 test "queues key as atom", %{conn: conn} do
2743 post(conn, "/api/pleroma/admin/config", %{
2749 %{"tuple" => [":federator_incoming", 50]},
2750 %{"tuple" => [":federator_outgoing", 50]},
2751 %{"tuple" => [":web_push", 50]},
2752 %{"tuple" => [":mailer", 10]},
2753 %{"tuple" => [":transmogrifier", 20]},
2754 %{"tuple" => [":scheduled_activities", 10]},
2755 %{"tuple" => [":background", 5]}
2761 assert json_response(conn, 200) == %{
2767 %{"tuple" => [":federator_incoming", 50]},
2768 %{"tuple" => [":federator_outgoing", 50]},
2769 %{"tuple" => [":web_push", 50]},
2770 %{"tuple" => [":mailer", 10]},
2771 %{"tuple" => [":transmogrifier", 20]},
2772 %{"tuple" => [":scheduled_activities", 10]},
2773 %{"tuple" => [":background", 5]}
2780 test "delete part of settings by atom subkeys", %{conn: conn} do
2784 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2788 post(conn, "/api/pleroma/admin/config", %{
2791 group: config.group,
2793 subkeys: [":subkey1", ":subkey3"],
2799 assert json_response(conn, 200) == %{
2802 "group" => ":pleroma",
2804 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2810 test "proxy tuple localhost", %{conn: conn} do
2812 post(conn, "/api/pleroma/admin/config", %{
2818 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]},
2819 %{"tuple" => [":send_user_agent", false]}
2825 assert json_response(conn, 200) == %{
2828 "group" => ":pleroma",
2831 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]},
2832 %{"tuple" => [":send_user_agent", false]}
2839 test "proxy tuple domain", %{conn: conn} do
2841 post(conn, "/api/pleroma/admin/config", %{
2847 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]},
2848 %{"tuple" => [":send_user_agent", false]}
2854 assert json_response(conn, 200) == %{
2857 "group" => ":pleroma",
2860 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]},
2861 %{"tuple" => [":send_user_agent", false]}
2868 test "proxy tuple ip", %{conn: conn} do
2870 post(conn, "/api/pleroma/admin/config", %{
2876 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]},
2877 %{"tuple" => [":send_user_agent", false]}
2883 assert json_response(conn, 200) == %{
2886 "group" => ":pleroma",
2889 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]},
2890 %{"tuple" => [":send_user_agent", false]}
2898 describe "config mix tasks run" do
2899 setup %{conn: conn} do
2900 admin = insert(:user, is_admin: true)
2902 Mix.shell(Mix.Shell.Quiet)
2905 Mix.shell(Mix.Shell.IO)
2908 %{conn: assign(conn, :user, admin)}
2911 clear_config([:instance, :dynamic_configuration]) do
2912 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2915 clear_config([:feed, :post_title]) do
2916 Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
2919 test "transfer settings to DB and to file", %{conn: conn} do
2920 on_exit(fn -> :ok = File.rm("config/test.exported_from_db.secret.exs") end)
2921 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2922 Mix.Tasks.Pleroma.Config.run(["migrate_to_db"])
2923 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2925 conn = get(conn, "/api/pleroma/admin/config/migrate_from_db")
2927 assert json_response(conn, 200) == %{}
2928 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2931 test "returns error if dynamic configuration is off", %{conn: conn} do
2932 initial = Pleroma.Config.get([:instance, :dynamic_configuration])
2933 on_exit(fn -> Pleroma.Config.put([:instance, :dynamic_configuration], initial) end)
2934 Pleroma.Config.put([:instance, :dynamic_configuration], false)
2936 conn = get(conn, "/api/pleroma/admin/config/migrate_from_db")
2938 assert json_response(conn, 400) ==
2939 "To use this endpoint you need to enable dynamic configuration."
2943 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2945 admin = insert(:user, is_admin: true)
2946 user = insert(:user)
2948 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2949 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2950 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2952 insert(:note_activity, user: user, published: date1)
2953 insert(:note_activity, user: user, published: date2)
2954 insert(:note_activity, user: user, published: date3)
2958 |> assign(:user, admin)
2960 {:ok, conn: conn, user: user}
2963 test "renders user's statuses", %{conn: conn, user: user} do
2964 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2966 assert json_response(conn, 200) |> length() == 3
2969 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2970 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2972 assert json_response(conn, 200) |> length() == 2
2975 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2976 {:ok, _private_status} =
2977 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2979 {:ok, _public_status} =
2980 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2982 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2984 assert json_response(conn, 200) |> length() == 4
2987 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2988 {:ok, _private_status} =
2989 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2991 {:ok, _public_status} =
2992 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2994 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2996 assert json_response(conn, 200) |> length() == 5
3000 describe "GET /api/pleroma/admin/moderation_log" do
3001 setup %{conn: conn} do
3002 admin = insert(:user, is_admin: true)
3003 moderator = insert(:user, is_moderator: true)
3005 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
3008 test "returns the log", %{conn: conn, admin: admin} do
3009 Repo.insert(%ModerationLog{
3013 "nickname" => admin.nickname,
3016 action: "relay_follow",
3017 target: "https://example.org/relay"
3019 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
3022 Repo.insert(%ModerationLog{
3026 "nickname" => admin.nickname,
3029 action: "relay_unfollow",
3030 target: "https://example.org/relay"
3032 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
3035 conn = get(conn, "/api/pleroma/admin/moderation_log")
3037 response = json_response(conn, 200)
3038 [first_entry, second_entry] = response["items"]
3040 assert response["total"] == 2
3041 assert first_entry["data"]["action"] == "relay_unfollow"
3043 assert first_entry["message"] ==
3044 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
3046 assert second_entry["data"]["action"] == "relay_follow"
3048 assert second_entry["message"] ==
3049 "@#{admin.nickname} followed relay: https://example.org/relay"
3052 test "returns the log with pagination", %{conn: conn, admin: admin} do
3053 Repo.insert(%ModerationLog{
3057 "nickname" => admin.nickname,
3060 action: "relay_follow",
3061 target: "https://example.org/relay"
3063 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
3066 Repo.insert(%ModerationLog{
3070 "nickname" => admin.nickname,
3073 action: "relay_unfollow",
3074 target: "https://example.org/relay"
3076 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
3079 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
3081 response1 = json_response(conn1, 200)
3082 [first_entry] = response1["items"]
3084 assert response1["total"] == 2
3085 assert response1["items"] |> length() == 1
3086 assert first_entry["data"]["action"] == "relay_unfollow"
3088 assert first_entry["message"] ==
3089 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
3091 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
3093 response2 = json_response(conn2, 200)
3094 [second_entry] = response2["items"]
3096 assert response2["total"] == 2
3097 assert response2["items"] |> length() == 1
3098 assert second_entry["data"]["action"] == "relay_follow"
3100 assert second_entry["message"] ==
3101 "@#{admin.nickname} followed relay: https://example.org/relay"
3104 test "filters log by date", %{conn: conn, admin: admin} do
3105 first_date = "2017-08-15T15:47:06Z"
3106 second_date = "2017-08-20T15:47:06Z"
3108 Repo.insert(%ModerationLog{
3112 "nickname" => admin.nickname,
3115 action: "relay_follow",
3116 target: "https://example.org/relay"
3118 inserted_at: NaiveDateTime.from_iso8601!(first_date)
3121 Repo.insert(%ModerationLog{
3125 "nickname" => admin.nickname,
3128 action: "relay_unfollow",
3129 target: "https://example.org/relay"
3131 inserted_at: NaiveDateTime.from_iso8601!(second_date)
3137 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
3140 response1 = json_response(conn1, 200)
3141 [first_entry] = response1["items"]
3143 assert response1["total"] == 1
3144 assert first_entry["data"]["action"] == "relay_unfollow"
3146 assert first_entry["message"] ==
3147 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
3150 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
3151 Repo.insert(%ModerationLog{
3155 "nickname" => admin.nickname,
3158 action: "relay_follow",
3159 target: "https://example.org/relay"
3163 Repo.insert(%ModerationLog{
3166 "id" => moderator.id,
3167 "nickname" => moderator.nickname,
3170 action: "relay_unfollow",
3171 target: "https://example.org/relay"
3175 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
3177 response1 = json_response(conn1, 200)
3178 [first_entry] = response1["items"]
3180 assert response1["total"] == 1
3181 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
3184 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
3185 ModerationLog.insert_log(%{
3187 action: "relay_follow",
3188 target: "https://example.org/relay"
3191 ModerationLog.insert_log(%{
3193 action: "relay_unfollow",
3194 target: "https://example.org/relay"
3197 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
3199 response1 = json_response(conn1, 200)
3200 [first_entry] = response1["items"]
3202 assert response1["total"] == 1
3204 assert get_in(first_entry, ["data", "message"]) ==
3205 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
3209 describe "PATCH /users/:nickname/force_password_reset" do
3210 setup %{conn: conn} do
3211 admin = insert(:user, is_admin: true)
3212 user = insert(:user)
3214 %{conn: assign(conn, :user, admin), admin: admin, user: user}
3217 test "sets password_reset_pending to true", %{admin: admin, user: user} do
3218 assert user.password_reset_pending == false
3222 |> assign(:user, admin)
3223 |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
3225 assert json_response(conn, 204) == ""
3227 ObanHelpers.perform_all()
3229 assert User.get_by_id(user.id).password_reset_pending == true
3233 describe "relays" do
3234 setup %{conn: conn} do
3235 admin = insert(:user, is_admin: true)
3237 %{conn: assign(conn, :user, admin), admin: admin}
3240 test "POST /relay", %{admin: admin} do
3243 |> assign(:user, admin)
3244 |> post("/api/pleroma/admin/relay", %{
3245 relay_url: "http://mastodon.example.org/users/admin"
3248 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
3250 log_entry = Repo.one(ModerationLog)
3252 assert ModerationLog.get_log_entry_message(log_entry) ==
3253 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
3256 test "GET /relay", %{admin: admin} do
3257 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
3259 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
3260 |> Enum.each(fn ap_id ->
3261 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
3262 User.follow(relay_user, user)
3267 |> assign(:user, admin)
3268 |> get("/api/pleroma/admin/relay")
3270 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
3273 test "DELETE /relay", %{admin: admin} do
3275 |> assign(:user, admin)
3276 |> post("/api/pleroma/admin/relay", %{
3277 relay_url: "http://mastodon.example.org/users/admin"
3282 |> assign(:user, admin)
3283 |> delete("/api/pleroma/admin/relay", %{
3284 relay_url: "http://mastodon.example.org/users/admin"
3287 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
3289 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
3291 assert ModerationLog.get_log_entry_message(log_entry_one) ==
3292 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
3294 assert ModerationLog.get_log_entry_message(log_entry_two) ==
3295 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
3299 describe "instances" do
3300 test "GET /instances/:instance/statuses" do
3301 admin = insert(:user, is_admin: true)
3302 user = insert(:user, local: false, nickname: "archaeme@archae.me")
3303 user2 = insert(:user, local: false, nickname: "test@test.com")
3304 insert_pair(:note_activity, user: user)
3305 insert(:note_activity, user: user2)
3309 |> assign(:user, admin)
3310 |> get("/api/pleroma/admin/instances/archae.me/statuses")
3312 response = json_response(conn, 200)
3314 assert length(response) == 2
3318 |> assign(:user, admin)
3319 |> get("/api/pleroma/admin/instances/test.com/statuses")
3321 response = json_response(conn, 200)
3323 assert length(response) == 1
3327 |> assign(:user, admin)
3328 |> get("/api/pleroma/admin/instances/nonexistent.com/statuses")
3330 response = json_response(conn, 200)
3332 assert length(response) == 0
3336 describe "PATCH /confirm_email" do
3337 setup %{conn: conn} do
3338 admin = insert(:user, is_admin: true)
3340 %{conn: assign(conn, :user, admin), admin: admin}
3343 test "it confirms emails of two users", %{admin: admin} do
3344 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
3346 assert first_user.confirmation_pending == true
3347 assert second_user.confirmation_pending == true
3350 |> assign(:user, admin)
3351 |> patch("/api/pleroma/admin/users/confirm_email", %{
3353 first_user.nickname,
3354 second_user.nickname
3358 assert first_user.confirmation_pending == true
3359 assert second_user.confirmation_pending == true
3361 log_entry = Repo.one(ModerationLog)
3363 assert ModerationLog.get_log_entry_message(log_entry) ==
3364 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
3365 second_user.nickname
3370 describe "PATCH /resend_confirmation_email" do
3371 setup %{conn: conn} do
3372 admin = insert(:user, is_admin: true)
3374 %{conn: assign(conn, :user, admin), admin: admin}
3377 test "it resend emails for two users", %{admin: admin} do
3378 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
3381 |> assign(:user, admin)
3382 |> patch("/api/pleroma/admin/users/resend_confirmation_email", %{
3384 first_user.nickname,
3385 second_user.nickname
3389 log_entry = Repo.one(ModerationLog)
3391 assert ModerationLog.get_log_entry_message(log_entry) ==
3392 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
3393 second_user.nickname
3398 describe "POST /reports/:id/notes" do
3400 admin = insert(:user, is_admin: true)
3401 [reporter, target_user] = insert_pair(:user)
3402 activity = insert(:note_activity, user: target_user)
3404 {:ok, %{id: report_id}} =
3405 CommonAPI.report(reporter, %{
3406 "account_id" => target_user.id,
3407 "comment" => "I feel offended",
3408 "status_ids" => [activity.id]
3412 |> assign(:user, admin)
3413 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
3414 content: "this is disgusting!"
3418 |> assign(:user, admin)
3419 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
3420 content: "this is disgusting2!"
3425 report_id: report_id,
3430 test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
3431 [note, _] = Repo.all(ReportNote)
3434 activity_id: ^report_id,
3435 content: "this is disgusting!",
3440 test "it returns reports with notes", %{admin: admin} do
3443 |> assign(:user, admin)
3444 |> get("/api/pleroma/admin/reports")
3446 response = json_response(conn, 200)
3447 notes = hd(response["reports"])["notes"]
3450 assert note["user"]["nickname"] == admin.nickname
3451 assert note["content"] == "this is disgusting!"
3452 assert note["created_at"]
3453 assert response["total"] == 1
3456 test "it deletes the note", %{admin: admin, report_id: report_id} do
3457 assert ReportNote |> Repo.all() |> length() == 2
3459 [note, _] = Repo.all(ReportNote)
3462 |> assign(:user, admin)
3463 |> delete("/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
3465 assert ReportNote |> Repo.all() |> length() == 1
3469 test "GET /api/pleroma/admin/config/descriptions", %{conn: conn} do
3470 admin = insert(:user, is_admin: true)
3473 assign(conn, :user, admin)
3474 |> get("/api/pleroma/admin/config/descriptions")
3476 assert [child | _others] = json_response(conn, 200)
3478 assert child["children"]
3480 assert String.starts_with?(child["group"], ":")
3481 assert child["description"]
3485 # Needed for testing
3486 defmodule Pleroma.Web.Endpoint.NotReal do
3489 defmodule Pleroma.Captcha.NotReal do