Commit e80e55d9 authored by Ilja's avatar Ilja
Browse files

Add "moderation_tag:manage-user-tags

I made sure that users who can set tags, can't set tags starting with "moderation_tag:". Otherwise they can easily give themselves, or any one else, any of the moderation rights.
parent bb389904
Pipeline #39880 passed with stages
in 21 minutes and 4 seconds
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.DissallowParam do
@moduledoc """
Forbids an action for specified parameters.
"""
import Pleroma.Web.TranslationHelpers
import Plug.Conn
def init(options) do
options
end
def call(%{params: params} = conn, {tag, regex}) do
if allowed?(params |> Map.get(tag), regex),
do: conn,
else:
conn |> render_error(:forbidden, "Call not allowed with specified parameter.") |> halt()
end
def call(conn, _) do
conn
end
defp allowed?(nil, _) do
true
end
defp allowed?(param_values, regex) do
not Enum.any?(param_values, fn value -> String.match?(value, regex) end)
end
end
......@@ -110,9 +110,10 @@ defmodule Pleroma.Web.Router do
plug(Pleroma.Web.Plugs.EnsureUserTag, "moderation_tag:report-triage")
end
pipeline :require_moderation_tag_posts_restriction do
pipeline :require_moderation_tag_manage_user_tags do
plug(:admin_api)
plug(Pleroma.Web.Plugs.EnsureUserTag, "moderation_tag:posts-restriction")
plug(Pleroma.Web.Plugs.EnsureUserTag, "moderation_tag:manage-user-tags")
plug(Pleroma.Web.Plugs.DissallowParam, {"tags", ~r/^moderation_tag:.*/})
end
pipeline :require_moderation_tag_post_deletion do
......@@ -265,9 +266,6 @@ defmodule Pleroma.Web.Router do
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/approve", UserController, :approve)
post("/users/invite_token", InviteController, :create)
......@@ -306,9 +304,12 @@ defmodule Pleroma.Web.Router do
end
# AdminAPI
# admins and mods (staff) with moderation_tag:posts-restriction can perform these actions
# admins and mods (staff) with moderation_tag:manage-user-tags can perform these actions
scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
pipe_through(:require_moderation_tag_posts_restriction)
pipe_through(:require_moderation_tag_manage_user_tags)
put("/users/tag", AdminAPIController, :tag_users)
delete("/users/tag", AdminAPIController, :untag_users)
end
# AdminAPI
......@@ -336,7 +337,7 @@ defmodule Pleroma.Web.Router do
end
# AdminAPI
# admins and mods (staff) with moderation_tag:account-deactivation can perform these actions
# admins and mods (staff) with moderation_tag:account-activation can perform these actions
scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
pipe_through(:require_moderation_tag_account_activation)
......
......@@ -28,7 +28,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
admin =
insert(:user,
is_admin: true,
tags: ["moderation_tag:messages-read-non-public", "moderation_tag:account-credentials"]
tags: [
"moderation_tag:messages-read-non-public",
"moderation_tag:account-credentials",
"moderation_tag:manage-user-tags"
]
)
token = insert(:oauth_admin_token, user: admin)
......@@ -100,8 +104,19 @@ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or bro
user1 = insert(:user, %{tags: ["x"]})
user2 = insert(:user, %{tags: ["y"]})
user3 = insert(:user, %{tags: ["unchanged"]})
%{conn: conn, user1: user1, user2: user2, user3: user3}
end
test "it requires user tag moderation_tag:manage-user-tags", %{
conn: conn,
user1: user1,
user2: user2
} do
conn =
conn.assigns.user.tags
|> put_in(conn.assigns.user.tags -- ["moderation_tag:manage-user-tags"])
response =
conn
|> put_req_header("accept", "application/json")
|> put(
......@@ -109,7 +124,30 @@ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or bro
"#{user2.nickname}&tags[]=foo&tags[]=bar"
)
%{conn: conn, user1: user1, user2: user2, user3: user3}
assert json_response(response, :forbidden)
end
test "it forbids when trying to set tags if one starts with 'moderation_tag:'", %{
conn: conn,
user1: user1,
user2: user2
} do
conn =
conn.assigns.user.tags
|> put_in(conn.assigns.user.tags)
response =
conn
|> put_req_header("accept", "application/json")
|> put(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
"#{user2.nickname}&tags[]=foo&tags[]=moderation_tag:something&tags[]=bar"
)
assert json_response(response, :forbidden)
# assert other tags aren't applied either
assert User.get_cached_by_id(user1.id).tags == ["x"]
assert User.get_cached_by_id(user2.id).tags == ["y"]
end
test "it appends specified tags to users with specified nicknames", %{
......@@ -118,6 +156,14 @@ test "it appends specified tags to users with specified nicknames", %{
user1: user1,
user2: user2
} do
conn =
conn
|> put_req_header("accept", "application/json")
|> put(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
"#{user2.nickname}&tags[]=foo&tags[]=bar"
)
assert empty_json_response(conn)
assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
......@@ -135,7 +181,20 @@ test "it appends specified tags to users with specified nicknames", %{
"@#{admin.nickname} added tags: #{tags} to users: #{users}"
end
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
test "it does not modify tags of not specified users", %{
conn: conn,
user1: user1,
user2: user2,
user3: user3
} do
conn =
conn
|> put_req_header("accept", "application/json")
|> put(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
"#{user2.nickname}&tags[]=foo&tags[]=bar"
)
assert empty_json_response(conn)
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
end
......@@ -147,7 +206,19 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user
user2 = insert(:user, %{tags: ["y", "z"]})
user3 = insert(:user, %{tags: ["unchanged"]})
%{conn: conn, user1: user1, user2: user2, user3: user3}
end
test "it requires user tag moderation_tag:manage-user-tags", %{
conn: conn,
user1: user1,
user2: user2
} do
conn =
conn.assigns.user.tags
|> put_in(conn.assigns.user.tags -- ["moderation_tag:manage-user-tags"])
response =
conn
|> put_req_header("accept", "application/json")
|> delete(
......@@ -155,7 +226,30 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user
"#{user2.nickname}&tags[]=x&tags[]=z"
)
%{conn: conn, user1: user1, user2: user2, user3: user3}
assert json_response(response, :forbidden)
end
test "it forbids when trying to set tags if one starts with 'moderation_tag:'", %{
conn: conn,
user1: user1,
user2: user2
} do
conn =
conn.assigns.user.tags
|> put_in(conn.assigns.user.tags)
response =
conn
|> put_req_header("accept", "application/json")
|> delete(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
"#{user2.nickname}&tags[]=x&tags[]=moderation_tag:something&tags[]=z"
)
assert json_response(response, :forbidden)
# assert other tags aren't deleted either
assert User.get_cached_by_id(user1.id).tags == ["x"]
assert User.get_cached_by_id(user2.id).tags == ["y", "z"]
end
test "it removes specified tags from users with specified nicknames", %{
......@@ -164,6 +258,14 @@ test "it removes specified tags from users with specified nicknames", %{
user1: user1,
user2: user2
} do
conn =
conn
|> put_req_header("accept", "application/json")
|> delete(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
"#{user2.nickname}&tags[]=x&tags[]=z"
)
assert empty_json_response(conn)
assert User.get_cached_by_id(user1.id).tags == []
assert User.get_cached_by_id(user2.id).tags == ["y"]
......@@ -181,7 +283,20 @@ test "it removes specified tags from users with specified nicknames", %{
"@#{admin.nickname} removed tags: #{tags} from users: #{users}"
end
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
test "it does not modify tags of not specified users", %{
conn: conn,
user1: user1,
user2: user2,
user3: user3
} do
conn =
conn
|> put_req_header("accept", "application/json")
|> delete(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
"#{user2.nickname}&tags[]=x&tags[]=z"
)
assert empty_json_response(conn)
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
end
......
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.DissallowParamTest do
use Pleroma.Web.ConnCase, async: true
alias Pleroma.Web.Plugs.DissallowParam
test "Doesn't allow a forbidden param" do
conn_forbidden =
build_conn(:get, "/", %{"tags" => ["foo", "moderation_tag:something", "bar"]})
conn_allowed = build_conn(:get, "/", %{"tags" => ["foo", "bar"]})
conn_no_value = build_conn()
ret_conn_forbidden = DissallowParam.call(conn_forbidden, {"tags", ~r/^moderation_tag:.*/})
ret_conn_allowed = DissallowParam.call(conn_allowed, {"tags", ~r/^moderation_tag:.*/})
ret_conn_no_value = DissallowParam.call(conn_no_value, {"tags", ~r/^moderation_tag:.*/})
assert ret_conn_forbidden.status == 403
assert ret_conn_allowed == conn_allowed
assert ret_conn_no_value == conn_no_value
end
end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment