diff --git a/lib/pleroma/web/plugs/user_is_staff_plug.ex b/lib/pleroma/web/plugs/user_is_staff_plug.ex new file mode 100644 index 0000000000..49c2d9ccae --- /dev/null +++ b/lib/pleroma/web/plugs/user_is_staff_plug.ex @@ -0,0 +1,23 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Plugs.UserIsStaffPlug do + import Pleroma.Web.TranslationHelpers + import Plug.Conn + + alias Pleroma.User + + def init(options) do + options + end + + def call(%{assigns: %{user: %User{is_admin: true}}} = conn, _), do: conn + def call(%{assigns: %{user: %User{is_moderator: true}}} = conn, _), do: conn + + def call(conn, _) do + conn + |> render_error(:forbidden, "User is not a staff member.") + |> halt() + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index a35deebe6d..62f98d114c 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -96,10 +96,14 @@ defmodule Pleroma.Web.Router do plug(Pleroma.Web.Plugs.AdminSecretAuthenticationPlug) plug(:after_auth) plug(Pleroma.Web.Plugs.EnsureAuthenticatedPlug) - plug(Pleroma.Web.Plugs.UserIsAdminPlug) + plug(Pleroma.Web.Plugs.UserIsStaffPlug) plug(Pleroma.Web.Plugs.IdempotencyPlug) end + pipeline :require_admin do + plug(Pleroma.Web.Plugs.UserIsAdminPlug) + end + pipeline :mastodon_html do plug(:browser) plug(:authenticate) @@ -159,12 +163,11 @@ defmodule Pleroma.Web.Router do post("/uploader_callback/:upload_path", UploaderController, :callback) end + # AdminAPI: only admins can perform these actions scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do - pipe_through(:admin_api) + pipe_through([:admin_api, :require_admin]) put("/users/disable_mfa", AdminAPIController, :disable_mfa) - put("/users/tag", AdminAPIController, :tag_users) - delete("/users/tag", AdminAPIController, :untag_users) get("/users/:nickname/permission_group", AdminAPIController, :right_get) get("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_get) @@ -187,34 +190,17 @@ defmodule Pleroma.Web.Router do post("/users/follow", UserController, :follow) post("/users/unfollow", UserController, :unfollow) - delete("/users", UserController, :delete) post("/users", UserController, :create) - patch("/users/:nickname/toggle_activation", UserController, :toggle_activation) - patch("/users/activate", UserController, :activate) - patch("/users/deactivate", UserController, :deactivate) - patch("/users/approve", UserController, :approve) get("/relay", RelayController, :index) post("/relay", RelayController, :follow) delete("/relay", RelayController, :unfollow) - post("/users/invite_token", InviteController, :create) - get("/users/invites", InviteController, :index) - post("/users/revoke_invite", InviteController, :revoke) - post("/users/email_invite", InviteController, :email) - get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset) patch("/users/force_password_reset", AdminAPIController, :force_password_reset) get("/users/:nickname/credentials", AdminAPIController, :show_user_credentials) patch("/users/:nickname/credentials", AdminAPIController, :update_user_credentials) - get("/users", UserController, :list) - get("/users/:nickname", UserController, :show) - get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) - get("/users/:nickname/chats", AdminAPIController, :list_user_chats) - - get("/instances/:instance/statuses", AdminAPIController, :list_instance_statuses) - get("/instance_document/:name", InstanceDocumentController, :show) patch("/instance_document/:name", InstanceDocumentController, :update) delete("/instance_document/:name", InstanceDocumentController, :delete) @@ -222,6 +208,57 @@ defmodule Pleroma.Web.Router do patch("/users/confirm_email", AdminAPIController, :confirm_email) patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email) + get("/config", ConfigController, :show) + post("/config", ConfigController, :update) + get("/config/descriptions", ConfigController, :descriptions) + get("/need_reboot", AdminAPIController, :need_reboot) + get("/restart", AdminAPIController, :restart) + + get("/oauth_app", OAuthAppController, :index) + post("/oauth_app", OAuthAppController, :create) + patch("/oauth_app/:id", OAuthAppController, :update) + delete("/oauth_app/:id", OAuthAppController, :delete) + + get("/media_proxy_caches", MediaProxyCacheController, :index) + post("/media_proxy_caches/delete", MediaProxyCacheController, :delete) + post("/media_proxy_caches/purge", MediaProxyCacheController, :purge) + + get("/frontends", FrontendController, :index) + post("/frontends/install", FrontendController, :install) + + post("/backups", AdminAPIController, :create_backup) + + get("/email_list/subscribers.csv", EmailListController, :subscribers) + get("/email_list/unsubscribers.csv", EmailListController, :unsubscribers) + get("/email_list/combined.csv", EmailListController, :combined) + end + + # AdminAPI: admins and mods (staff) can perform these actions + scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do + pipe_through(:admin_api) + + put("/users/tag", AdminAPIController, :tag_users) + delete("/users/tag", AdminAPIController, :untag_users) + + patch("/users/:nickname/toggle_activation", UserController, :toggle_activation) + patch("/users/activate", UserController, :activate) + patch("/users/deactivate", UserController, :deactivate) + patch("/users/approve", UserController, :approve) + + delete("/users", UserController, :delete) + + post("/users/invite_token", InviteController, :create) + get("/users/invites", InviteController, :index) + post("/users/revoke_invite", InviteController, :revoke) + post("/users/email_invite", InviteController, :email) + + get("/users", UserController, :list) + get("/users/:nickname", UserController, :show) + get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) + get("/users/:nickname/chats", AdminAPIController, :list_user_chats) + + get("/instances/:instance/statuses", AdminAPIController, :list_instance_statuses) + get("/reports", ReportController, :index) get("/reports/:id", ReportController, :show) patch("/reports", ReportController, :update) @@ -233,38 +270,14 @@ defmodule Pleroma.Web.Router do delete("/statuses/:id", StatusController, :delete) get("/statuses", StatusController, :index) - get("/config", ConfigController, :show) - post("/config", ConfigController, :update) - get("/config/descriptions", ConfigController, :descriptions) - get("/need_reboot", AdminAPIController, :need_reboot) - get("/restart", AdminAPIController, :restart) - get("/moderation_log", AdminAPIController, :list_log) post("/reload_emoji", AdminAPIController, :reload_emoji) get("/stats", AdminAPIController, :stats) - get("/oauth_app", OAuthAppController, :index) - post("/oauth_app", OAuthAppController, :create) - patch("/oauth_app/:id", OAuthAppController, :update) - delete("/oauth_app/:id", OAuthAppController, :delete) - - get("/media_proxy_caches", MediaProxyCacheController, :index) - post("/media_proxy_caches/delete", MediaProxyCacheController, :delete) - post("/media_proxy_caches/purge", MediaProxyCacheController, :purge) - get("/chats/:id", ChatController, :show) get("/chats/:id/messages", ChatController, :messages) delete("/chats/:id/messages/:message_id", ChatController, :delete_message) - - get("/frontends", FrontendController, :index) - post("/frontends/install", FrontendController, :install) - - post("/backups", AdminAPIController, :create_backup) - - get("/email_list/subscribers.csv", EmailListController, :subscribers) - get("/email_list/unsubscribers.csv", EmailListController, :unsubscribers) - get("/email_list/combined.csv", EmailListController, :combined) end scope "/api/v1/pleroma/emoji", Pleroma.Web.PleromaAPI do diff --git a/test/pleroma/web/admin_api/controllers/report_controller_test.exs b/test/pleroma/web/admin_api/controllers/report_controller_test.exs index 6a2986b5ff..8102845d57 100644 --- a/test/pleroma/web/admin_api/controllers/report_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/report_controller_test.exs @@ -305,7 +305,7 @@ test "returns 403 when requested by a non-admin" do |> get("/api/pleroma/admin/reports") assert json_response(conn, :forbidden) == - %{"error" => "User is not an admin."} + %{"error" => "User is not a staff member."} end test "returns 403 when requested by anonymous" do diff --git a/test/pleroma/web/plugs/user_is_staff_plug_test.exs b/test/pleroma/web/plugs/user_is_staff_plug_test.exs new file mode 100644 index 0000000000..a0c4061dba --- /dev/null +++ b/test/pleroma/web/plugs/user_is_staff_plug_test.exs @@ -0,0 +1,47 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Plugs.UserIsStaffPlugTest do + use Pleroma.Web.ConnCase, async: true + + alias Pleroma.Web.Plugs.UserIsStaffPlug + import Pleroma.Factory + + test "accepts a user that is an admin" do + user = insert(:user, is_admin: true) + + conn = assign(build_conn(), :user, user) + + ret_conn = UserIsStaffPlug.call(conn, %{}) + + assert conn == ret_conn + end + + test "accepts a user that is a moderator" do + user = insert(:user, is_moderator: true) + + conn = assign(build_conn(), :user, user) + + ret_conn = UserIsStaffPlug.call(conn, %{}) + + assert conn == ret_conn + end + + test "denies a user that isn't a staff member" do + user = insert(:user) + + conn = + build_conn() + |> assign(:user, user) + |> UserIsStaffPlug.call(%{}) + + assert conn.status == 403 + end + + test "denies when a user isn't set" do + conn = UserIsStaffPlug.call(build_conn(), %{}) + + assert conn.status == 403 + end +end