API: optionally restrict moderators from accessing sensitive data
authorAlibek Omarov <a1ba.omarov@gmail.com>
Sun, 26 Dec 2021 23:27:48 +0000 (02:27 +0300)
committerAlibek Omarov <a1ba.omarov@gmail.com>
Sun, 26 Dec 2021 23:27:48 +0000 (02:27 +0300)
CHANGELOG.md
config/config.exs
config/description.exs
lib/pleroma/web/plugs/ensure_staff_privileged.ex [new file with mode: 0644]
lib/pleroma/web/router.ex

index ee9e0456854b4165975101152bc557a7a0a7b16e..79fe674a9dfecb68af737caaa49ab45f4274fdd1 100644 (file)
@@ -15,6 +15,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 ### Added
 - `activeMonth` and `activeHalfyear` fields in NodeInfo usage.users object
+- AdminAPI: allow moderators to manage reports, users, invites, and custom emojis
+- AdminAPI: restrict moderators to access sensitive data: change user credentials, get password reset token, read private statuses and chats, etc
 
 ### Fixed
 - Subscription(Bell) Notifications: Don't create from Pipeline Ingested replies
@@ -67,7 +69,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Attachment dimensions and blurhashes are federated when available.
 - Mastodon API: support `poll` notification.
 - Pinned posts federation
-- AdminAPI: allow moderators to manage reports, users, invites, and custom emojis
 
 ### Fixed
 - Don't crash so hard when email settings are invalid.
index 23c41edddaf789cd1fe51d43733b1be654154578..ec242cadcb48306f5112e1013615da5045c06202 100644 (file)
@@ -255,7 +255,8 @@ config :pleroma, :instance,
   ],
   show_reactions: true,
   password_reset_token_validity: 60 * 60 * 24,
-  profile_directory: true
+  profile_directory: true,
+  privileged_staff: false
 
 config :pleroma, :welcome,
   direct_message: [
index 517077acf58be36d757a5a2b262932df3e44e06b..a8fbd4d73be9854ffc211247cd5528e3f7327ed3 100644 (file)
@@ -941,6 +941,11 @@ config :pleroma, :config_description, [
         key: :profile_directory,
         type: :boolean,
         description: "Enable profile directory."
+      },
+      %{
+        key: :privileged_staff,
+        type: :boolean,
+        description: "Let moderators access sensitive data (e.g. updating user credentials, get password reset token, delete users, index and read private statuses and chats)"
       }
     ]
   },
diff --git a/lib/pleroma/web/plugs/ensure_staff_privileged.ex b/lib/pleroma/web/plugs/ensure_staff_privileged.ex
new file mode 100644 (file)
index 0000000..b15ddfc
--- /dev/null
@@ -0,0 +1,31 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Plugs.EnsureStaffPrivilegedPlug do
+  @moduledoc """
+  Ensures if staff are privileged enough to do certain tasks
+  """
+
+  import Pleroma.Web.TranslationHelpers
+  import Plug.Conn
+
+  alias Pleroma.User
+  alias Pleroma.Config
+
+  def init(options) do
+    options
+  end
+
+  def call(%{assigns: %{user: %User{is_admin: true}}} = conn, _), do: conn
+
+  def call(conn, _) do
+    if Config.get!([:instance, :privileged_staff]) do
+      conn
+    else
+      conn
+      |> render_error(:forbidden, "User is not an admin.")
+      |> halt()
+    end
+  end
+end
index b2ca0978436ce3a8a2bf14b6dcef73f8e0a21ca0..7ba72994b3a9611b29f3078e87387538f0f1fe5f 100644 (file)
@@ -101,6 +101,10 @@ defmodule Pleroma.Web.Router do
     plug(Pleroma.Web.Plugs.IdempotencyPlug)
   end
 
+  pipeline :require_privileged_staff do
+    plug(Pleroma.Web.Plugs.EnsureStaffPrivilegedPlug)
+  end
+
   pipeline :require_admin do
     plug(Pleroma.Web.Plugs.UserIsAdminPlug)
   end
@@ -228,6 +232,24 @@ defmodule Pleroma.Web.Router do
     post("/backups", AdminAPIController, :create_backup)
   end
 
+  # AdminAPI: admins and mods (staff) can perform these actions (if enabled by config)
+  scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+    pipe_through([:admin_api, :require_privileged_staff])
+
+    delete("/users", UserController, :delete)
+
+    get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset)
+    patch("/users/:nickname/credentials", AdminAPIController, :update_user_credentials)    
+
+    get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
+    get("/users/:nickname/chats", AdminAPIController, :list_user_chats)
+
+    get("/statuses", StatusController, :index)
+
+    get("/chats/:id", ChatController, :show)
+    get("/chats/:id/messages", ChatController, :messages)
+  end
+
   # AdminAPI: admins and mods (staff) can perform these actions
   scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
     pipe_through(:admin_api)
@@ -240,22 +262,16 @@ defmodule Pleroma.Web.Router do
     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/: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, :index)
     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", InstanceController, :list_statuses)
     delete("/instances/:instance", InstanceController, :delete)
@@ -269,15 +285,12 @@ defmodule Pleroma.Web.Router do
     get("/statuses/:id", StatusController, :show)
     put("/statuses/:id", StatusController, :update)
     delete("/statuses/:id", StatusController, :delete)
-    get("/statuses", StatusController, :index)
 
     get("/moderation_log", AdminAPIController, :list_log)
 
     post("/reload_emoji", AdminAPIController, :reload_emoji)
     get("/stats", AdminAPIController, :stats)
 
-    get("/chats/:id", ChatController, :show)
-    get("/chats/:id/messages", ChatController, :messages)
     delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
   end