1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 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
10 import Pleroma.Factory
11 import Swoosh.TestAssertions
13 alias Pleroma.Activity
15 alias Pleroma.ModerationLog
17 alias Pleroma.Tests.ObanHelpers
19 alias Pleroma.Web.CommonAPI
22 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
28 admin = insert(:user, is_admin: true)
29 token = insert(:oauth_admin_token, user: admin)
33 |> assign(:user, admin)
34 |> assign(:token, token)
36 {:ok, %{admin: admin, token: token, conn: conn}}
39 test "with valid `admin_token` query parameter, skips OAuth scopes check" do
40 clear_config([:admin_token], "password123")
44 conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123")
46 assert json_response(conn, 200)
49 describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
50 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
52 test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
55 url = "/api/pleroma/admin/users/#{user.nickname}"
57 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
58 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
59 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
61 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
62 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
65 for good_token <- [good_token1, good_token2, good_token3] do
68 |> assign(:user, admin)
69 |> assign(:token, good_token)
72 assert json_response(conn, 200)
75 for good_token <- [good_token1, good_token2, good_token3] do
79 |> assign(:token, good_token)
82 assert json_response(conn, :forbidden)
85 for bad_token <- [bad_token1, bad_token2, bad_token3] do
88 |> assign(:user, admin)
89 |> assign(:token, bad_token)
92 assert json_response(conn, :forbidden)
97 describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
98 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
100 test "GET /api/pleroma/admin/users/:nickname requires " <>
101 "read:accounts or admin:read:accounts or broader scope",
104 url = "/api/pleroma/admin/users/#{user.nickname}"
106 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
107 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
108 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
109 good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
110 good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])
112 good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]
114 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
115 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
118 for good_token <- good_tokens do
121 |> assign(:user, admin)
122 |> assign(:token, good_token)
125 assert json_response(conn, 200)
128 for good_token <- good_tokens do
131 |> assign(:user, nil)
132 |> assign(:token, good_token)
135 assert json_response(conn, :forbidden)
138 for bad_token <- [bad_token1, bad_token2, bad_token3] do
141 |> assign(:user, admin)
142 |> assign(:token, bad_token)
145 assert json_response(conn, :forbidden)
150 describe "PUT /api/pleroma/admin/users/tag" do
151 setup %{conn: conn} do
152 user1 = insert(:user, %{tags: ["x"]})
153 user2 = insert(:user, %{tags: ["y"]})
154 user3 = insert(:user, %{tags: ["unchanged"]})
158 |> put_req_header("accept", "application/json")
160 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
161 "#{user2.nickname}&tags[]=foo&tags[]=bar"
164 %{conn: conn, user1: user1, user2: user2, user3: user3}
167 test "it appends specified tags to users with specified nicknames", %{
173 assert empty_json_response(conn)
174 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
175 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
177 log_entry = Repo.one(ModerationLog)
180 [user1.nickname, user2.nickname]
181 |> Enum.map(&"@#{&1}")
184 tags = ["foo", "bar"] |> Enum.join(", ")
186 assert ModerationLog.get_log_entry_message(log_entry) ==
187 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
190 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
191 assert empty_json_response(conn)
192 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
196 describe "DELETE /api/pleroma/admin/users/tag" do
197 setup %{conn: conn} do
198 user1 = insert(:user, %{tags: ["x"]})
199 user2 = insert(:user, %{tags: ["y", "z"]})
200 user3 = insert(:user, %{tags: ["unchanged"]})
204 |> put_req_header("accept", "application/json")
206 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
207 "#{user2.nickname}&tags[]=x&tags[]=z"
210 %{conn: conn, user1: user1, user2: user2, user3: user3}
213 test "it removes specified tags from users with specified nicknames", %{
219 assert empty_json_response(conn)
220 assert User.get_cached_by_id(user1.id).tags == []
221 assert User.get_cached_by_id(user2.id).tags == ["y"]
223 log_entry = Repo.one(ModerationLog)
226 [user1.nickname, user2.nickname]
227 |> Enum.map(&"@#{&1}")
230 tags = ["x", "z"] |> Enum.join(", ")
232 assert ModerationLog.get_log_entry_message(log_entry) ==
233 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
236 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
237 assert empty_json_response(conn)
238 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
242 describe "/api/pleroma/admin/users/:nickname/permission_group" do
243 test "GET is giving user_info", %{admin: admin, conn: conn} do
246 |> put_req_header("accept", "application/json")
247 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
249 assert json_response(conn, 200) == %{
251 "is_moderator" => false
255 test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do
260 |> put_req_header("accept", "application/json")
261 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
263 assert json_response(conn, 200) == %{
267 log_entry = Repo.one(ModerationLog)
269 assert ModerationLog.get_log_entry_message(log_entry) ==
270 "@#{admin.nickname} made @#{user.nickname} admin"
273 test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do
274 user_one = insert(:user)
275 user_two = insert(:user)
279 |> put_req_header("accept", "application/json")
280 |> post("/api/pleroma/admin/users/permission_group/admin", %{
281 nicknames: [user_one.nickname, user_two.nickname]
284 assert json_response(conn, 200) == %{"is_admin" => true}
286 log_entry = Repo.one(ModerationLog)
288 assert ModerationLog.get_log_entry_message(log_entry) ==
289 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
292 test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do
293 user = insert(:user, is_admin: true)
297 |> put_req_header("accept", "application/json")
298 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
300 assert json_response(conn, 200) == %{"is_admin" => false}
302 log_entry = Repo.one(ModerationLog)
304 assert ModerationLog.get_log_entry_message(log_entry) ==
305 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
308 test "/:right DELETE, can remove from a permission group (multiple)", %{
312 user_one = insert(:user, is_admin: true)
313 user_two = insert(:user, is_admin: true)
317 |> put_req_header("accept", "application/json")
318 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
319 nicknames: [user_one.nickname, user_two.nickname]
322 assert json_response(conn, 200) == %{"is_admin" => false}
324 log_entry = Repo.one(ModerationLog)
326 assert ModerationLog.get_log_entry_message(log_entry) ==
327 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
333 test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
338 |> put_req_header("accept", "application/json")
339 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
341 resp = json_response(conn, 200)
343 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
346 describe "PUT disable_mfa" do
347 test "returns 200 and disable 2fa", %{conn: conn} do
350 multi_factor_authentication_settings: %MFA.Settings{
352 totp: %MFA.Settings.TOTP{secret: "otp_secret", confirmed: true}
358 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: user.nickname})
359 |> json_response(200)
361 assert response == user.nickname
362 mfa_settings = refresh_record(user).multi_factor_authentication_settings
364 refute mfa_settings.enabled
365 refute mfa_settings.totp.confirmed
368 test "returns 404 if user not found", %{conn: conn} do
371 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
372 |> json_response(404)
374 assert response == %{"error" => "Not found"}
378 describe "GET /api/pleroma/admin/restart" do
379 setup do: clear_config(:configurable_from_database, true)
381 test "pleroma restarts", %{conn: conn} do
383 assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
384 end) =~ "pleroma restarted"
386 refute Restarter.Pleroma.need_reboot?()
390 test "need_reboot flag", %{conn: conn} do
392 |> get("/api/pleroma/admin/need_reboot")
393 |> json_response(200) == %{"need_reboot" => false}
395 Restarter.Pleroma.need_reboot()
398 |> get("/api/pleroma/admin/need_reboot")
399 |> json_response(200) == %{"need_reboot" => true}
401 on_exit(fn -> Restarter.Pleroma.refresh() end)
404 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
408 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
409 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
410 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
412 insert(:note_activity, user: user, published: date1)
413 insert(:note_activity, user: user, published: date2)
414 insert(:note_activity, user: user, published: date3)
419 test "renders user's statuses", %{conn: conn, user: user} do
420 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
422 assert json_response(conn, 200) |> length() == 3
425 test "renders user's statuses with pagination", %{conn: conn, user: user} do
426 conn1 = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=1")
428 response1 = json_response(conn1, 200)
430 assert response1 |> length() == 1
432 conn2 = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=2")
434 response2 = json_response(conn2, 200)
436 assert response2 |> length() == 1
438 refute response1 == response2
441 test "doesn't return private statuses by default", %{conn: conn, user: user} do
442 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
444 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
446 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
448 assert json_response(conn, 200) |> length() == 4
451 test "returns private statuses with godmode on", %{conn: conn, user: user} do
452 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
454 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
456 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
458 assert json_response(conn, 200) |> length() == 5
461 test "excludes reblogs by default", %{conn: conn, user: user} do
462 other_user = insert(:user)
463 {:ok, activity} = CommonAPI.post(user, %{status: "."})
464 {:ok, %Activity{}} = CommonAPI.repeat(activity.id, other_user)
466 conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses")
467 assert json_response(conn_res, 200) |> length() == 0
470 get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true")
472 assert json_response(conn_res, 200) |> length() == 1
476 describe "GET /api/pleroma/admin/users/:nickname/chats" do
479 recipients = insert_list(3, :user)
481 Enum.each(recipients, fn recipient ->
482 CommonAPI.post_chat_message(user, recipient, "yo")
488 test "renders user's chats", %{conn: conn, user: user} do
489 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/chats")
491 assert json_response(conn, 200) |> length() == 3
495 describe "GET /api/pleroma/admin/users/:nickname/chats unauthorized" do
498 recipient = insert(:user)
499 CommonAPI.post_chat_message(user, recipient, "yo")
500 %{conn: conn} = oauth_access(["read:chats"])
501 %{conn: conn, user: user}
504 test "returns 403", %{conn: conn, user: user} do
506 |> get("/api/pleroma/admin/users/#{user.nickname}/chats")
507 |> json_response(403)
511 describe "GET /api/pleroma/admin/users/:nickname/chats unauthenticated" do
514 recipient = insert(:user)
515 CommonAPI.post_chat_message(user, recipient, "yo")
516 %{conn: build_conn(), user: user}
519 test "returns 403", %{conn: conn, user: user} do
521 |> get("/api/pleroma/admin/users/#{user.nickname}/chats")
522 |> json_response(403)
526 describe "GET /api/pleroma/admin/moderation_log" do
528 moderator = insert(:user, is_moderator: true)
530 %{moderator: moderator}
533 test "returns the log", %{conn: conn, admin: admin} do
534 Repo.insert(%ModerationLog{
538 "nickname" => admin.nickname,
541 action: "relay_follow",
542 target: "https://example.org/relay"
544 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
547 Repo.insert(%ModerationLog{
551 "nickname" => admin.nickname,
554 action: "relay_unfollow",
555 target: "https://example.org/relay"
557 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
560 conn = get(conn, "/api/pleroma/admin/moderation_log")
562 response = json_response(conn, 200)
563 [first_entry, second_entry] = response["items"]
565 assert response["total"] == 2
566 assert first_entry["data"]["action"] == "relay_unfollow"
568 assert first_entry["message"] ==
569 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
571 assert second_entry["data"]["action"] == "relay_follow"
573 assert second_entry["message"] ==
574 "@#{admin.nickname} followed relay: https://example.org/relay"
577 test "returns the log with pagination", %{conn: conn, admin: admin} do
578 Repo.insert(%ModerationLog{
582 "nickname" => admin.nickname,
585 action: "relay_follow",
586 target: "https://example.org/relay"
588 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
591 Repo.insert(%ModerationLog{
595 "nickname" => admin.nickname,
598 action: "relay_unfollow",
599 target: "https://example.org/relay"
601 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
604 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
606 response1 = json_response(conn1, 200)
607 [first_entry] = response1["items"]
609 assert response1["total"] == 2
610 assert response1["items"] |> length() == 1
611 assert first_entry["data"]["action"] == "relay_unfollow"
613 assert first_entry["message"] ==
614 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
616 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
618 response2 = json_response(conn2, 200)
619 [second_entry] = response2["items"]
621 assert response2["total"] == 2
622 assert response2["items"] |> length() == 1
623 assert second_entry["data"]["action"] == "relay_follow"
625 assert second_entry["message"] ==
626 "@#{admin.nickname} followed relay: https://example.org/relay"
629 test "filters log by date", %{conn: conn, admin: admin} do
630 first_date = "2017-08-15T15:47:06Z"
631 second_date = "2017-08-20T15:47:06Z"
633 Repo.insert(%ModerationLog{
637 "nickname" => admin.nickname,
640 action: "relay_follow",
641 target: "https://example.org/relay"
643 inserted_at: NaiveDateTime.from_iso8601!(first_date)
646 Repo.insert(%ModerationLog{
650 "nickname" => admin.nickname,
653 action: "relay_unfollow",
654 target: "https://example.org/relay"
656 inserted_at: NaiveDateTime.from_iso8601!(second_date)
662 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
665 response1 = json_response(conn1, 200)
666 [first_entry] = response1["items"]
668 assert response1["total"] == 1
669 assert first_entry["data"]["action"] == "relay_unfollow"
671 assert first_entry["message"] ==
672 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
675 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
676 Repo.insert(%ModerationLog{
680 "nickname" => admin.nickname,
683 action: "relay_follow",
684 target: "https://example.org/relay"
688 Repo.insert(%ModerationLog{
691 "id" => moderator.id,
692 "nickname" => moderator.nickname,
695 action: "relay_unfollow",
696 target: "https://example.org/relay"
700 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
702 response1 = json_response(conn1, 200)
703 [first_entry] = response1["items"]
705 assert response1["total"] == 1
706 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
709 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
710 ModerationLog.insert_log(%{
712 action: "relay_follow",
713 target: "https://example.org/relay"
716 ModerationLog.insert_log(%{
718 action: "relay_unfollow",
719 target: "https://example.org/relay"
722 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
724 response1 = json_response(conn1, 200)
725 [first_entry] = response1["items"]
727 assert response1["total"] == 1
729 assert get_in(first_entry, ["data", "message"]) ==
730 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
734 test "gets a remote users when [:instance, :limit_to_local_content] is set to :unauthenticated",
736 clear_config(Pleroma.Config.get([:instance, :limit_to_local_content]), :unauthenticated)
737 user = insert(:user, %{local: false, nickname: "u@peer1.com"})
738 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
740 assert json_response(conn, 200)
743 describe "GET /users/:nickname/credentials" do
744 test "gets the user credentials", %{conn: conn} do
746 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
748 response = assert json_response(conn, 200)
749 assert response["email"] == user.email
752 test "returns 403 if requested by a non-admin" do
757 |> assign(:user, user)
758 |> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
760 assert json_response(conn, :forbidden)
764 describe "PATCH /users/:nickname/credentials" do
770 test "changes password and email", %{conn: conn, admin: admin, user: user} do
771 assert user.password_reset_pending == false
774 patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
775 "password" => "new_password",
776 "email" => "new_email@example.com",
780 assert json_response(conn, 200) == %{"status" => "success"}
782 ObanHelpers.perform_all()
784 updated_user = User.get_by_id(user.id)
786 assert updated_user.email == "new_email@example.com"
787 assert updated_user.name == "new_name"
788 assert updated_user.password_hash != user.password_hash
789 assert updated_user.password_reset_pending == true
791 [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
793 assert ModerationLog.get_log_entry_message(log_entry1) ==
794 "@#{admin.nickname} updated users: @#{user.nickname}"
796 assert ModerationLog.get_log_entry_message(log_entry2) ==
797 "@#{admin.nickname} forced password reset for users: @#{user.nickname}"
800 test "returns 403 if requested by a non-admin", %{user: user} do
803 |> assign(:user, user)
804 |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
805 "password" => "new_password",
806 "email" => "new_email@example.com",
810 assert json_response(conn, :forbidden)
813 test "changes actor type from permitted list", %{conn: conn, user: user} do
814 assert user.actor_type == "Person"
816 assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
817 "actor_type" => "Service"
819 |> json_response(200) == %{"status" => "success"}
821 updated_user = User.get_by_id(user.id)
823 assert updated_user.actor_type == "Service"
825 assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
826 "actor_type" => "Application"
828 |> json_response(400) == %{"errors" => %{"actor_type" => "is invalid"}}
831 test "update non existing user", %{conn: conn} do
832 assert patch(conn, "/api/pleroma/admin/users/non-existing/credentials", %{
833 "password" => "new_password"
835 |> json_response(404) == %{"error" => "Not found"}
839 describe "PATCH /users/:nickname/force_password_reset" do
840 test "sets password_reset_pending to true", %{conn: conn} do
842 assert user.password_reset_pending == false
845 patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
847 assert empty_json_response(conn) == ""
849 ObanHelpers.perform_all()
851 assert User.get_by_id(user.id).password_reset_pending == true
855 describe "instances" do
856 test "GET /instances/:instance/statuses", %{conn: conn} do
857 user = insert(:user, local: false, ap_id: "https://archae.me/users/archaeme")
858 user2 = insert(:user, local: false, ap_id: "https://test.com/users/test")
859 insert_pair(:note_activity, user: user)
860 activity = insert(:note_activity, user: user2)
862 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
864 response = json_response(ret_conn, 200)
866 assert length(response) == 2
868 ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses")
870 response = json_response(ret_conn, 200)
872 assert length(response) == 1
874 ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses")
876 response = json_response(ret_conn, 200)
878 assert Enum.empty?(response)
880 CommonAPI.repeat(activity.id, user)
882 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
883 response = json_response(ret_conn, 200)
884 assert length(response) == 2
886 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
887 response = json_response(ret_conn, 200)
888 assert length(response) == 3
892 describe "PATCH /confirm_email" do
893 test "it confirms emails of two users", %{conn: conn, admin: admin} do
894 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
896 assert first_user.confirmation_pending == true
897 assert second_user.confirmation_pending == true
900 patch(conn, "/api/pleroma/admin/users/confirm_email", %{
907 assert ret_conn.status == 200
909 assert first_user.confirmation_pending == true
910 assert second_user.confirmation_pending == true
912 log_entry = Repo.one(ModerationLog)
914 assert ModerationLog.get_log_entry_message(log_entry) ==
915 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
921 describe "PATCH /resend_confirmation_email" do
922 test "it resend emails for two users", %{conn: conn, admin: admin} do
923 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
926 patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{
933 assert ret_conn.status == 200
935 log_entry = Repo.one(ModerationLog)
937 assert ModerationLog.get_log_entry_message(log_entry) ==
938 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
942 ObanHelpers.perform_all()
944 Pleroma.Emails.UserEmail.account_confirmation_email(first_user)
945 # temporary hackney fix until hackney max_connections bug is fixed
946 # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
947 |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
948 |> assert_email_sent()
952 describe "/api/pleroma/admin/stats" do
953 test "status visibility count", %{conn: conn} do
955 CommonAPI.post(user, %{visibility: "public", status: "hey"})
956 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
957 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
961 |> get("/api/pleroma/admin/stats")
962 |> json_response(200)
964 assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
965 response["status_visibility"]
968 test "by instance", %{conn: conn} do
969 user1 = insert(:user)
970 instance2 = "instance2.tld"
971 user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
973 CommonAPI.post(user1, %{visibility: "public", status: "hey"})
974 CommonAPI.post(user2, %{visibility: "unlisted", status: "hey"})
975 CommonAPI.post(user2, %{visibility: "private", status: "hey"})
979 |> get("/api/pleroma/admin/stats", instance: instance2)
980 |> json_response(200)
982 assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
983 response["status_visibility"]
987 describe "/api/pleroma/backups" do
988 test "it creates a backup", %{conn: conn} do
989 admin = %{id: admin_id, nickname: admin_nickname} = insert(:user, is_admin: true)
990 token = insert(:oauth_admin_token, user: admin)
991 user = %{id: user_id, nickname: user_nickname} = insert(:user)
995 |> assign(:user, admin)
996 |> assign(:token, token)
997 |> post("/api/pleroma/admin/backups", %{nickname: user.nickname})
998 |> json_response(200)
1000 assert [backup] = Repo.all(Pleroma.User.Backup)
1002 ObanHelpers.perform_all()
1004 email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup, admin.id)
1006 assert String.contains?(email.html_body, "Admin @#{admin.nickname} requested a full backup")
1007 assert_email_sent(to: {user.name, user.email}, html_body: email.html_body)
1009 log_message = "@#{admin_nickname} requested account backup for @#{user_nickname}"
1014 "action" => "create_backup",
1017 "nickname" => ^admin_nickname
1019 "message" => ^log_message,
1022 "nickname" => ^user_nickname
1026 ] = Pleroma.ModerationLog |> Repo.all()
1029 test "it doesn't limit admins", %{conn: conn} do
1030 admin = insert(:user, is_admin: true)
1031 token = insert(:oauth_admin_token, user: admin)
1032 user = insert(:user)
1036 |> assign(:user, admin)
1037 |> assign(:token, token)
1038 |> post("/api/pleroma/admin/backups", %{nickname: user.nickname})
1039 |> json_response(200)
1041 assert [_backup] = Repo.all(Pleroma.User.Backup)
1045 |> assign(:user, admin)
1046 |> assign(:token, token)
1047 |> post("/api/pleroma/admin/backups", %{nickname: user.nickname})
1048 |> json_response(200)
1050 assert Repo.aggregate(Pleroma.User.Backup, :count) == 2
1055 # Needed for testing
1056 defmodule Pleroma.Web.Endpoint.NotReal do
1059 defmodule Pleroma.Captcha.NotReal do