From c64c4454d7addb32ba450ba5714cd782a1a78537 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 15 Mar 2023 19:20:36 -0500 Subject: [PATCH] Prevent moderators from deleting admins --- .../admin_api/controllers/user_controller.ex | 35 +++++++++++----- .../controllers/user_controller_test.exs | 42 +++++++++++++++++++ 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex index 7b4ee46a4e..2bc170a8d1 100644 --- a/lib/pleroma/web/admin_api/controllers/user_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex @@ -60,20 +60,35 @@ def delete(conn, %{nickname: nickname}) do def delete(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do users = Enum.map(nicknames, &User.get_cached_by_nickname/1) - Enum.each(users, fn user -> - {:ok, delete_data, _} = Builder.delete(admin, user.ap_id) - Pipeline.common_pipeline(delete_data, local: true) - end) + if Enum.all?(users, &is_higher_role(admin, &1)) do + Enum.each(users, fn user -> + {:ok, delete_data, _} = Builder.delete(admin, user.ap_id) + Pipeline.common_pipeline(delete_data, local: true) + end) - ModerationLog.insert_log(%{ - actor: admin, - subject: users, - action: "delete" - }) + ModerationLog.insert_log(%{ + actor: admin, + subject: users, + action: "delete" + }) - json(conn, nicknames) + json(conn, nicknames) + else + conn + |> put_status(:forbidden) + |> json(%{error: dgettext("errors", "Forbidden")}) + end end + # true if actor is greater OR EQUAL in role to target + defp is_higher_role(%User{} = actor, %User{} = target) do + role_weight(actor) >= role_weight(target) + end + + defp role_weight(%User{is_admin: true}), do: 2 + defp role_weight(%User{is_moderator: true}), do: 1 + defp role_weight(_), do: 0 + def follow( %{ assigns: %{user: admin}, diff --git a/test/pleroma/web/admin_api/controllers/user_controller_test.exs b/test/pleroma/web/admin_api/controllers/user_controller_test.exs index bb9dcb4aae..1b87eb9d4c 100644 --- a/test/pleroma/web/admin_api/controllers/user_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/user_controller_test.exs @@ -139,6 +139,48 @@ test "Needs privileged role", %{conn: conn} do assert json_response(response, :forbidden) end + + test "Moderators can't delete admins" do + admin = insert(:user, is_admin: true) + moderator = insert(:user, is_moderator: true) + token = insert(:oauth_admin_token, user: moderator) + + conn = + build_conn() + |> assign(:user, moderator) + |> assign(:token, token) + + response = + conn + |> put_req_header("accept", "application/json") + |> put_req_header("content-type", "application/json") + |> delete("/api/pleroma/admin/users", %{ + nicknames: [admin.nickname] + }) + + assert json_response(response, :forbidden) + end + + test "Moderators can delete other moderators" do + moderator1 = insert(:user, is_moderator: true) + moderator2 = insert(:user, is_moderator: true) + token = insert(:oauth_admin_token, user: moderator1) + + conn = + build_conn() + |> assign(:user, moderator1) + |> assign(:token, token) + + response = + conn + |> put_req_header("accept", "application/json") + |> put_req_header("content-type", "application/json") + |> delete("/api/pleroma/admin/users", %{ + nicknames: [moderator2.nickname] + }) + + assert json_response(response, 200) + end end describe "/api/pleroma/admin/users" do