fix(mastodon-api): harden admin moderation actions
This commit is contained in:
parent
a5aad47cff
commit
458a15bf9f
10 changed files with 344 additions and 31 deletions
|
|
@ -1016,6 +1016,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|
|
||||||
defp restrict_state(query, _), do: query
|
defp restrict_state(query, _), do: query
|
||||||
|
|
||||||
|
defp restrict_report_target(query, %{report_target_id: actor_id}) do
|
||||||
|
from(activity in query,
|
||||||
|
where: fragment("?->'object'->>0 = ?", activity.data, ^actor_id)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp restrict_report_target(query, _), do: query
|
||||||
|
|
||||||
defp restrict_assigned_account(query, %{assigned_account: assigned_account}) do
|
defp restrict_assigned_account(query, %{assigned_account: assigned_account}) do
|
||||||
from(activity in query,
|
from(activity in query,
|
||||||
where: fragment("?->>'assigned_account' = ?", activity.data, ^assigned_account)
|
where: fragment("?->>'assigned_account' = ?", activity.data, ^assigned_account)
|
||||||
|
|
@ -1514,6 +1522,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
|> restrict_actor(opts)
|
|> restrict_actor(opts)
|
||||||
|> restrict_type(opts)
|
|> restrict_type(opts)
|
||||||
|> restrict_state(opts)
|
|> restrict_state(opts)
|
||||||
|
|> restrict_report_target(opts)
|
||||||
|> restrict_assigned_account(opts)
|
|> restrict_assigned_account(opts)
|
||||||
|> restrict_favorited_by(opts)
|
|> restrict_favorited_by(opts)
|
||||||
|> restrict_blocked(restrict_blocked_opts)
|
|> restrict_blocked(restrict_blocked_opts)
|
||||||
|
|
|
||||||
|
|
@ -216,20 +216,24 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.AccountOperation do
|
||||||
properties: %{
|
properties: %{
|
||||||
type: %Schema{
|
type: %Schema{
|
||||||
type: :string,
|
type: :string,
|
||||||
enum: ["none", "disable", "sensitive", "silence", "suspend"]
|
enum: ["none", "disable"]
|
||||||
},
|
},
|
||||||
report_id: %Schema{
|
report_id: %Schema{
|
||||||
type: :string,
|
type: :string,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "ID of an associated report that caused this action to be taken"
|
description: "ID of an associated report that caused this action to be taken"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
required: [:type]
|
||||||
},
|
},
|
||||||
required: true
|
required: true
|
||||||
),
|
),
|
||||||
responses: %{
|
responses: %{
|
||||||
204 => no_content_response(),
|
204 => no_content_response(),
|
||||||
401 => Operation.response("Error", "application/json", ApiError)
|
400 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
401 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
403 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
404 => Operation.response("Error", "application/json", ApiError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do
|
||||||
:target_account_id,
|
:target_account_id,
|
||||||
:query,
|
:query,
|
||||||
:string,
|
:string,
|
||||||
"Filter by report target account id (not implemented)"
|
"Filter by report target account id"
|
||||||
)
|
)
|
||||||
] ++
|
] ++
|
||||||
pagination_params(),
|
pagination_params(),
|
||||||
|
|
@ -81,7 +81,8 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("Report", "application/json", report()),
|
200 => Operation.response("Report", "application/json", report()),
|
||||||
400 => Operation.response("Error", "application/json", ApiError),
|
400 => Operation.response("Error", "application/json", ApiError),
|
||||||
401 => Operation.response("Error", "application/json", ApiError)
|
401 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
404 => Operation.response("Error", "application/json", ApiError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
@ -99,11 +100,43 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("Report", "application/json", report()),
|
200 => Operation.response("Report", "application/json", report()),
|
||||||
400 => Operation.response("Error", "application/json", ApiError),
|
400 => Operation.response("Error", "application/json", ApiError),
|
||||||
401 => Operation.response("Error", "application/json", ApiError)
|
401 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
404 => Operation.response("Error", "application/json", ApiError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assign_to_self_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Report management (Mastodon API)"],
|
||||||
|
summary: "Assign report to self",
|
||||||
|
operationId: "MastodonAdmin.ReportController.assign_to_self",
|
||||||
|
security: [%{"oAuth" => ["admin:write:reports"]}],
|
||||||
|
parameters: [Operation.parameter(:id, :path, :string, "ID of the report")],
|
||||||
|
responses: report_update_responses()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def unassign_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Report management (Mastodon API)"],
|
||||||
|
summary: "Unassign report",
|
||||||
|
operationId: "MastodonAdmin.ReportController.unassign",
|
||||||
|
security: [%{"oAuth" => ["admin:write:reports"]}],
|
||||||
|
parameters: [Operation.parameter(:id, :path, :string, "ID of the report")],
|
||||||
|
responses: report_update_responses()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp report_update_responses do
|
||||||
|
%{
|
||||||
|
200 => Operation.response("Report", "application/json", report()),
|
||||||
|
400 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
401 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
404 => Operation.response("Error", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
defp report do
|
defp report do
|
||||||
%Schema{
|
%Schema{
|
||||||
title: "Admin::Report",
|
title: "Admin::Report",
|
||||||
|
|
@ -112,7 +145,7 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do
|
||||||
id: FlakeID,
|
id: FlakeID,
|
||||||
action_taken: %Schema{type: :boolean},
|
action_taken: %Schema{type: :boolean},
|
||||||
action_taken_at: %Schema{type: :string, format: "date-time", nullable: true},
|
action_taken_at: %Schema{type: :string, format: "date-time", nullable: true},
|
||||||
category: %Schema{type: :string, enum: ["spam", "violation", "other"]},
|
category: %Schema{type: :string, enum: ["spam", "legal", "violation", "other"]},
|
||||||
comment: %Schema{type: :string, nullable: true},
|
comment: %Schema{type: :string, nullable: true},
|
||||||
forwarded: %Schema{type: :boolean, nullable: true},
|
forwarded: %Schema{type: :boolean, nullable: true},
|
||||||
created_at: %Schema{type: :string, format: "date-time"},
|
created_at: %Schema{type: :string, format: "date-time"},
|
||||||
|
|
@ -136,7 +169,7 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do
|
||||||
items: %Schema{
|
items: %Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
properties: %{
|
properties: %{
|
||||||
id: %Schema{type: :integer},
|
id: %Schema{type: :string},
|
||||||
text: %Schema{type: :string}
|
text: %Schema{type: :string}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -700,7 +700,7 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_report_state(activity_id, state) do
|
def update_report_state(activity_id, state) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id(activity_id, filter: []) do
|
with %Activity{} = activity <- Activity.get_report(activity_id) do
|
||||||
Utils.update_report_state(activity, state)
|
Utils.update_report_state(activity, state)
|
||||||
else
|
else
|
||||||
nil -> {:error, :not_found}
|
nil -> {:error, :not_found}
|
||||||
|
|
@ -715,7 +715,7 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_report_to_account(activity_id, user) do
|
def assign_report_to_account(activity_id, user) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id(activity_id) do
|
with %Activity{} = activity <- Activity.get_report(activity_id) do
|
||||||
Utils.assign_report_to_account(activity, user)
|
Utils.assign_report_to_account(activity, user)
|
||||||
else
|
else
|
||||||
nil -> {:error, :not_found}
|
nil -> {:error, :not_found}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountController do
|
||||||
when action in [:index, :index2, :show]
|
when action in [:index, :index2, :show]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{scopes: ["admin:write:accounts"]}
|
%{scopes: ["admin:write:accounts"]}
|
||||||
|
|
@ -92,11 +94,18 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountController do
|
||||||
conn,
|
conn,
|
||||||
_params
|
_params
|
||||||
) do
|
) do
|
||||||
{:ok, _user} = handle_account_action(user, admin, type)
|
with :ok <- validate_account_action(user, type),
|
||||||
|
{:ok, report} <- associated_report(user, body_params),
|
||||||
|
:ok <- resolve_report(admin, report),
|
||||||
|
{:ok, _user} <- handle_account_action(user, admin, type) do
|
||||||
|
json_response(conn, :no_content, "")
|
||||||
|
else
|
||||||
|
{:error, :not_found} ->
|
||||||
|
{:error, :not_found}
|
||||||
|
|
||||||
resolve_report(admin, body_params)
|
{:error, error} ->
|
||||||
|
json_response(conn, :bad_request, %{error: error})
|
||||||
json_response(conn, :no_content, "")
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(%{assigns: %{user: admin, account: user}} = conn, _params) do
|
def delete(%{assigns: %{user: admin, account: user}} = conn, _params) do
|
||||||
|
|
@ -161,10 +170,21 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountController do
|
||||||
User.set_activation(user, false)
|
User.set_activation(user, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_account_action(user, _admin, _type) do
|
defp handle_account_action(%User{}, _admin, "disable") do
|
||||||
|
{:error, "Only local accounts can be disabled"}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp handle_account_action(user, _admin, "none") do
|
||||||
{:ok, user}
|
{:ok, user}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp validate_account_action(%User{local: true}, "disable"), do: :ok
|
||||||
|
|
||||||
|
defp validate_account_action(%User{}, "disable"),
|
||||||
|
do: {:error, "Only local accounts can be disabled"}
|
||||||
|
|
||||||
|
defp validate_account_action(%User{}, "none"), do: :ok
|
||||||
|
|
||||||
defp build_criteria(params) do
|
defp build_criteria(params) do
|
||||||
%{}
|
%{}
|
||||||
|> maybe_filter_local(params)
|
|> maybe_filter_local(params)
|
||||||
|
|
@ -251,7 +271,23 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountController do
|
||||||
defp unquote(:"maybe_filter_#{filter_param}")(criteria, _params), do: criteria
|
defp unquote(:"maybe_filter_#{filter_param}")(criteria, _params), do: criteria
|
||||||
end
|
end
|
||||||
|
|
||||||
defp resolve_report(admin, %{report_id: id}) do
|
defp associated_report(user, %{report_id: id}) do
|
||||||
|
case Activity.get_report(id) do
|
||||||
|
%Activity{data: %{"object" => [target_ap_id | _]}} = report
|
||||||
|
when target_ap_id == user.ap_id ->
|
||||||
|
{:ok, report}
|
||||||
|
|
||||||
|
%Activity{} ->
|
||||||
|
{:error, "Report does not target this account"}
|
||||||
|
|
||||||
|
nil ->
|
||||||
|
{:error, :not_found}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp associated_report(_user, _params), do: {:ok, nil}
|
||||||
|
|
||||||
|
defp resolve_report(admin, %Activity{id: id}) do
|
||||||
with {:ok, activity} <- CommonAPI.update_report_state(id, "resolved"),
|
with {:ok, activity} <- CommonAPI.update_report_state(id, "resolved"),
|
||||||
report <- Activity.get_by_id_with_user_actor(activity.id) do
|
report <- Activity.get_by_id_with_user_actor(activity.id) do
|
||||||
ModerationLog.insert_log(%{
|
ModerationLog.insert_log(%{
|
||||||
|
|
@ -260,9 +296,10 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountController do
|
||||||
subject: activity,
|
subject: activity,
|
||||||
subject_actor: report.user_actor
|
subject_actor: report.user_actor
|
||||||
})
|
})
|
||||||
|
|
||||||
|
:ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp resolve_report(_admin, _params) do
|
defp resolve_report(_admin, nil), do: :ok
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,13 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do
|
||||||
|
|
||||||
plug(OAuthScopesPlug, %{scopes: ["admin:write:reports"]} when action in [:resolve, :reopen])
|
plug(OAuthScopesPlug, %{scopes: ["admin:write:reports"]} when action in [:resolve, :reopen])
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["admin:write:reports"]} when action in [:assign_to_self, :unassign]
|
||||||
|
)
|
||||||
|
|
||||||
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation
|
||||||
|
|
||||||
def index(conn, params) do
|
def index(conn, params) do
|
||||||
|
|
@ -37,6 +44,7 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do
|
||||||
|> Map.put(:total, true)
|
|> Map.put(:total, true)
|
||||||
|> restrict_state(params)
|
|> restrict_state(params)
|
||||||
|> restrict_actor(params)
|
|> restrict_actor(params)
|
||||||
|
|> restrict_target(params)
|
||||||
|
|
||||||
reports =
|
reports =
|
||||||
ActivityPub.fetch_activities_query([], opts)
|
ActivityPub.fetch_activities_query([], opts)
|
||||||
|
|
@ -67,6 +75,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do
|
||||||
|
|
||||||
render(conn, "show.json", Report.extract_report_info(report))
|
render(conn, "show.json", Report.extract_report_info(report))
|
||||||
else
|
else
|
||||||
|
{:error, :not_found} ->
|
||||||
|
{:error, :not_found}
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
json_response(conn, :bad_request, %{error: error})
|
json_response(conn, :bad_request, %{error: error})
|
||||||
end
|
end
|
||||||
|
|
@ -84,6 +95,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do
|
||||||
|
|
||||||
render(conn, "show.json", Report.extract_report_info(report))
|
render(conn, "show.json", Report.extract_report_info(report))
|
||||||
else
|
else
|
||||||
|
{:error, :not_found} ->
|
||||||
|
{:error, :not_found}
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
json_response(conn, :bad_request, %{error: error})
|
json_response(conn, :bad_request, %{error: error})
|
||||||
end
|
end
|
||||||
|
|
@ -102,6 +116,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do
|
||||||
|
|
||||||
render(conn, "show.json", Report.extract_report_info(report))
|
render(conn, "show.json", Report.extract_report_info(report))
|
||||||
else
|
else
|
||||||
|
{:error, :not_found} ->
|
||||||
|
{:error, :not_found}
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
json_response(conn, :bad_request, %{error: error})
|
json_response(conn, :bad_request, %{error: error})
|
||||||
end
|
end
|
||||||
|
|
@ -119,14 +136,17 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do
|
||||||
|
|
||||||
render(conn, "show.json", Report.extract_report_info(report))
|
render(conn, "show.json", Report.extract_report_info(report))
|
||||||
else
|
else
|
||||||
|
{:error, :not_found} ->
|
||||||
|
{:error, :not_found}
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
json_response(conn, :bad_request, %{error: error})
|
json_response(conn, :bad_request, %{error: error})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict_state(opts, %{resolved: true}), do: Map.put(opts, :state, "resolved")
|
defp restrict_state(opts, %{resolved: true, unresolved: true}), do: opts
|
||||||
|
|
||||||
defp restrict_state(opts, %{resolved: _}), do: Map.put(opts, :state, "resolved")
|
defp restrict_state(opts, %{resolved: true}), do: Map.put(opts, :state, "resolved")
|
||||||
|
|
||||||
defp restrict_state(opts, _params), do: Map.put(opts, :state, "open")
|
defp restrict_state(opts, _params), do: Map.put(opts, :state, "open")
|
||||||
|
|
||||||
|
|
@ -139,4 +159,13 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict_actor(opts, _params), do: opts
|
defp restrict_actor(opts, _params), do: opts
|
||||||
|
|
||||||
|
defp restrict_target(opts, %{target_account_id: actor}) do
|
||||||
|
case User.get_by_id(actor) do
|
||||||
|
%User{ap_id: ap_id} -> Map.put(opts, :report_target_id, ap_id)
|
||||||
|
_ -> Map.put(opts, :report_target_id, actor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp restrict_target(opts, _params), do: opts
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportView do
|
||||||
use Pleroma.Web, :view
|
use Pleroma.Web, :view
|
||||||
|
|
||||||
alias Pleroma.HTML
|
alias Pleroma.HTML
|
||||||
|
alias Pleroma.Rule
|
||||||
alias Pleroma.Web.AdminAPI.Report
|
alias Pleroma.Web.AdminAPI.Report
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.MastodonAPI.Admin.AccountView
|
alias Pleroma.Web.MastodonAPI.Admin.AccountView
|
||||||
|
|
@ -21,9 +22,12 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportView do
|
||||||
report: report,
|
report: report,
|
||||||
user: account,
|
user: account,
|
||||||
account: target_account,
|
account: target_account,
|
||||||
statuses: statuses
|
statuses: statuses,
|
||||||
|
assigned_account: assigned_account
|
||||||
}) do
|
}) do
|
||||||
created_at = Utils.to_masto_date(report.data["published"])
|
created_at = Utils.to_masto_date(report.data["published"])
|
||||||
|
updated_at = Utils.to_masto_date(report.updated_at)
|
||||||
|
action_taken = report.data["state"] != "open"
|
||||||
|
|
||||||
content =
|
content =
|
||||||
unless is_nil(report.data["content"]) do
|
unless is_nil(report.data["content"]) do
|
||||||
|
|
@ -34,23 +38,34 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportView do
|
||||||
|
|
||||||
%{
|
%{
|
||||||
id: report.id,
|
id: report.id,
|
||||||
action_taken: report.data["state"] != "open",
|
action_taken: action_taken,
|
||||||
action_taken_at: nil,
|
action_taken_at: if(action_taken, do: updated_at),
|
||||||
category: "other",
|
category: "other",
|
||||||
comment: content,
|
comment: content,
|
||||||
forwarded: nil,
|
forwarded: false,
|
||||||
created_at: created_at,
|
created_at: created_at,
|
||||||
updated_at: created_at,
|
updated_at: updated_at,
|
||||||
account: AccountView.render("show.json", %{user: account}),
|
account: AccountView.render("show.json", %{user: account}),
|
||||||
target_account: AccountView.render("show.json", %{user: target_account}),
|
target_account: AccountView.render("show.json", %{user: target_account}),
|
||||||
assigned_account: nil,
|
assigned_account: render_account(assigned_account),
|
||||||
action_taken_by_account: nil,
|
action_taken_by_account: nil,
|
||||||
statuses:
|
statuses:
|
||||||
StatusView.render("index.json", %{
|
StatusView.render("index.json", %{
|
||||||
activities: statuses,
|
activities: statuses,
|
||||||
as: :activity
|
as: :activity
|
||||||
}),
|
}),
|
||||||
rules: []
|
rules: rules(report.data["rules"])
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp render_account(nil), do: nil
|
||||||
|
defp render_account(account), do: AccountView.render("show.json", %{user: account})
|
||||||
|
|
||||||
|
defp rules(nil), do: []
|
||||||
|
|
||||||
|
defp rules(rule_ids) do
|
||||||
|
rule_ids
|
||||||
|
|> Rule.get()
|
||||||
|
|> Enum.map(&%{id: to_string(&1.id), text: &1.text})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,12 @@ defmodule Pleroma.Web.Router do
|
||||||
plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_activation_state)
|
plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_activation_state)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pipeline :require_privileged_role_account_actions do
|
||||||
|
plug(:admin_api)
|
||||||
|
plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_activation_state)
|
||||||
|
plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :reports_manage_reports)
|
||||||
|
end
|
||||||
|
|
||||||
pipeline :require_privileged_role_users_manage_invites do
|
pipeline :require_privileged_role_users_manage_invites do
|
||||||
plug(:admin_api)
|
plug(:admin_api)
|
||||||
plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_invites)
|
plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_invites)
|
||||||
|
|
@ -443,10 +449,15 @@ defmodule Pleroma.Web.Router do
|
||||||
scope "/api/v1/admin", Pleroma.Web.MastodonAPI.Admin do
|
scope "/api/v1/admin", Pleroma.Web.MastodonAPI.Admin do
|
||||||
pipe_through([:require_privileged_role_users_manage_activation_state])
|
pipe_through([:require_privileged_role_users_manage_activation_state])
|
||||||
|
|
||||||
post("/accounts/:id/action", AccountController, :account_action)
|
|
||||||
post("/accounts/:id/enable", AccountController, :enable)
|
post("/accounts/:id/enable", AccountController, :enable)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scope "/api/v1/admin", Pleroma.Web.MastodonAPI.Admin do
|
||||||
|
pipe_through([:require_privileged_role_account_actions])
|
||||||
|
|
||||||
|
post("/accounts/:id/action", AccountController, :account_action)
|
||||||
|
end
|
||||||
|
|
||||||
# Mastodon AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
|
# Mastodon AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
|
||||||
scope "/api/v1/admin", Pleroma.Web.MastodonAPI.Admin do
|
scope "/api/v1/admin", Pleroma.Web.MastodonAPI.Admin do
|
||||||
pipe_through([:require_privileged_role_users_manage_invites])
|
pipe_through([:require_privileged_role_users_manage_invites])
|
||||||
|
|
@ -462,6 +473,8 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/reports/:id", ReportController, :show)
|
get("/reports/:id", ReportController, :show)
|
||||||
post("/reports/:id/resolve", ReportController, :resolve)
|
post("/reports/:id/resolve", ReportController, :resolve)
|
||||||
post("/reports/:id/reopen", ReportController, :reopen)
|
post("/reports/:id/reopen", ReportController, :reopen)
|
||||||
|
post("/reports/:id/assign_to_self", ReportController, :assign_to_self)
|
||||||
|
post("/reports/:id/unassign", ReportController, :unassign)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Mastodon AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
|
# Mastodon AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,20 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountControllerTest do
|
||||||
assert %{is_active: false} = user
|
assert %{is_active: false} = user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "does not disable a remote account", %{conn: conn} do
|
||||||
|
%{id: id} = user = insert(:user, local: false)
|
||||||
|
|
||||||
|
assert %{"error" => "Only local accounts can be disabled"} =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/admin/accounts/#{id}/action", %{
|
||||||
|
"type" => "disable"
|
||||||
|
})
|
||||||
|
|> json_response_and_validate_schema(400)
|
||||||
|
|
||||||
|
assert %{is_active: true} = Repo.reload!(user)
|
||||||
|
end
|
||||||
|
|
||||||
test "perform action with assigned report", %{conn: conn} do
|
test "perform action with assigned report", %{conn: conn} do
|
||||||
[reporter, target_user] = insert_pair(:user)
|
[reporter, target_user] = insert_pair(:user)
|
||||||
|
|
||||||
|
|
@ -191,11 +205,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountControllerTest do
|
||||||
account_id: target_user.id
|
account_id: target_user.id
|
||||||
})
|
})
|
||||||
|
|
||||||
%{id: id} = insert(:user)
|
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "application/json")
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/admin/accounts/#{id}/action", %{
|
|> post("/api/v1/admin/accounts/#{target_user.id}/action", %{
|
||||||
"type" => "none",
|
"type" => "none",
|
||||||
"report_id" => report_id
|
"report_id" => report_id
|
||||||
})
|
})
|
||||||
|
|
@ -205,6 +217,56 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountControllerTest do
|
||||||
|
|
||||||
assert %{data: %{"state" => "resolved"}} = report
|
assert %{data: %{"state" => "resolved"}} = report
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "requires the report management privilege", %{conn: conn} do
|
||||||
|
clear_config([:instance, :admin_privileges], [:users_manage_activation_state])
|
||||||
|
|
||||||
|
%{id: id} = insert(:user)
|
||||||
|
|
||||||
|
assert %{"error" => _} =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/admin/accounts/#{id}/action", %{"type" => "none"})
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not resolve a report for another account", %{conn: conn} do
|
||||||
|
[reporter, target_user, other_user] = insert_list(3, :user)
|
||||||
|
|
||||||
|
{:ok, report} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
account_id: target_user.id
|
||||||
|
})
|
||||||
|
|
||||||
|
assert %{"error" => _} =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/admin/accounts/#{other_user.id}/action", %{
|
||||||
|
"type" => "none",
|
||||||
|
"report_id" => report.id
|
||||||
|
})
|
||||||
|
|> json_response_and_validate_schema(400)
|
||||||
|
|
||||||
|
assert %{data: %{"state" => "open"}} = Repo.reload!(report)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "requires an action type", %{conn: conn} do
|
||||||
|
%{id: id} = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/admin/accounts/#{id}/action", %{})
|
||||||
|
|> json_response_and_validate_schema(400)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects unsupported action types", %{conn: conn} do
|
||||||
|
%{id: id} = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/admin/accounts/#{id}/action", %{"type" => "sensitive"})
|
||||||
|
|> json_response_and_validate_schema(400)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "POST /api/v1/admin/accounts/:id/enable" do
|
describe "POST /api/v1/admin/accounts/:id/enable" do
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportControllerTest do
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.Rule
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
setup_all do
|
setup_all do
|
||||||
|
|
@ -58,6 +61,11 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportControllerTest do
|
||||||
|> get("/api/v1/admin/reports")
|
|> get("/api/v1/admin/reports")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [%{"id" => ^report_id1}] =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/admin/reports?resolved=false")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert [%{"id" => ^report_id2}, %{"id" => ^report_id1}] =
|
assert [%{"id" => ^report_id2}, %{"id" => ^report_id1}] =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/admin/reports?resolved=true&unresolved=true")
|
|> get("/api/v1/admin/reports?resolved=true&unresolved=true")
|
||||||
|
|
@ -68,6 +76,25 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportControllerTest do
|
||||||
|> get("/api/v1/admin/reports?resolved=true")
|
|> get("/api/v1/admin/reports?resolved=true")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "get reports by target account", %{conn: conn} do
|
||||||
|
[reporter, target_user, other_target] = insert_list(3, :user)
|
||||||
|
|
||||||
|
{:ok, %{id: report_id}} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
account_id: target_user.id
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, _report} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
account_id: other_target.id
|
||||||
|
})
|
||||||
|
|
||||||
|
assert [%{"id" => ^report_id}] =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/admin/reports?target_account_id=#{target_user.id}")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /api/v1/admin/reports/:id" do
|
describe "GET /api/v1/admin/reports/:id" do
|
||||||
|
|
@ -86,6 +113,34 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportControllerTest do
|
||||||
|> get("/api/v1/admin/reports/#{report_id}")
|
|> get("/api/v1/admin/reports/#{report_id}")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "returns report rules", %{conn: conn} do
|
||||||
|
[reporter, target_user] = insert_pair(:user)
|
||||||
|
rule = Rule.create(%{text: "Be excellent to each other"})
|
||||||
|
|
||||||
|
{:ok, %{id: report_id}} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
account_id: target_user.id,
|
||||||
|
rule_ids: [rule.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
assert %{
|
||||||
|
"rules" => [
|
||||||
|
%{"id" => rule_id, "text" => "Be excellent to each other"}
|
||||||
|
]
|
||||||
|
} =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/admin/reports/#{report_id}")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert rule_id == to_string(rule.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 404 for a missing report", %{conn: conn} do
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/admin/reports/0")
|
||||||
|
|> json_response_and_validate_schema(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "POST /api/v1/admin/reports/:id/resolve" do
|
describe "POST /api/v1/admin/reports/:id/resolve" do
|
||||||
|
|
@ -104,6 +159,16 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportControllerTest do
|
||||||
|> post("/api/v1/admin/reports/#{report_id}/resolve")
|
|> post("/api/v1/admin/reports/#{report_id}/resolve")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "does not mutate a non-report activity", %{conn: conn} do
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/admin/reports/#{activity.id}/resolve")
|
||||||
|
|> json_response_and_validate_schema(404)
|
||||||
|
|
||||||
|
refute Repo.reload!(activity).data["state"]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "POST /api/v1/admin/reports/:id/reopen" do
|
describe "POST /api/v1/admin/reports/:id/reopen" do
|
||||||
|
|
@ -124,5 +189,51 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportControllerTest do
|
||||||
|> post("/api/v1/admin/reports/#{report_id}/reopen")
|
|> post("/api/v1/admin/reports/#{report_id}/reopen")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "does not mutate a non-report activity", %{conn: conn} do
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/admin/reports/#{activity.id}/reopen")
|
||||||
|
|> json_response_and_validate_schema(404)
|
||||||
|
|
||||||
|
refute Repo.reload!(activity).data["state"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "POST /api/v1/admin/reports/:id/assign_to_self" do
|
||||||
|
test "assign and unassign a report", %{admin: admin, conn: conn} do
|
||||||
|
[reporter, target_user] = insert_pair(:user)
|
||||||
|
|
||||||
|
{:ok, report} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
account_id: target_user.id
|
||||||
|
})
|
||||||
|
|
||||||
|
assert %{"assigned_account" => %{"id" => admin_id}} =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/admin/reports/#{report.id}/assign_to_self")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert admin_id == admin.id
|
||||||
|
assert Repo.reload!(report).data["assigned_account"] == admin.id
|
||||||
|
|
||||||
|
assert %{"assigned_account" => nil} =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/admin/reports/#{report.id}/unassign")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
refute Repo.reload!(report).data["assigned_account"]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not assign a non-report activity", %{conn: conn} do
|
||||||
|
%Activity{id: id} = activity = insert(:note_activity)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/admin/reports/#{id}/assign_to_self")
|
||||||
|
|> json_response_and_validate_schema(404)
|
||||||
|
|
||||||
|
refute Repo.reload!(activity).data["assigned_account"]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue