Merge branch 'openapi/reports' into 'develop'
Add OpenAPI spec for ReportController See merge request pleroma/pleroma!2434
This commit is contained in:
commit
607e06c245
|
@ -0,0 +1,78 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ApiSpec.ReportOperation do
|
||||||
|
alias OpenApiSpex.Operation
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
alias Pleroma.Web.ApiSpec.Helpers
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||||
|
|
||||||
|
def open_api_operation(action) do
|
||||||
|
operation = String.to_existing_atom("#{action}_operation")
|
||||||
|
apply(__MODULE__, operation, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["reports"],
|
||||||
|
summary: "File a report",
|
||||||
|
description: "Report problematic users to your moderators",
|
||||||
|
operationId: "ReportController.create",
|
||||||
|
security: [%{"oAuth" => ["follow", "write:reports"]}],
|
||||||
|
requestBody: Helpers.request_body("Parameters", create_request(), required: true),
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Report", "application/json", create_response()),
|
||||||
|
400 => Operation.response("Report", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp create_request do
|
||||||
|
%Schema{
|
||||||
|
title: "ReportCreateRequest",
|
||||||
|
description: "POST body for creating a report",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
account_id: %Schema{type: :string, description: "ID of the account to report"},
|
||||||
|
status_ids: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string},
|
||||||
|
description: "Array of Statuses to attach to the report, for context"
|
||||||
|
},
|
||||||
|
comment: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Reason for the report"
|
||||||
|
},
|
||||||
|
forward: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
default: false,
|
||||||
|
description:
|
||||||
|
"If the account is remote, should the report be forwarded to the remote admin?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
required: [:account_id],
|
||||||
|
example: %{
|
||||||
|
"account_id" => "123",
|
||||||
|
"status_ids" => ["1337"],
|
||||||
|
"comment" => "bad status!",
|
||||||
|
"forward" => "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp create_response do
|
||||||
|
%Schema{
|
||||||
|
title: "ReportResponse",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
id: %Schema{type: :string, description: "Report ID"},
|
||||||
|
action_taken: %Schema{type: :boolean, description: "Is action taken?"}
|
||||||
|
},
|
||||||
|
example: %{
|
||||||
|
"id" => "123",
|
||||||
|
"action_taken" => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -382,9 +382,9 @@ def thread_muted?(user, activity) do
|
||||||
ThreadMute.exists?(user.id, activity.data["context"])
|
ThreadMute.exists?(user.id, activity.data["context"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def report(user, %{"account_id" => account_id} = data) do
|
def report(user, data) do
|
||||||
with {:ok, account} <- get_reported_account(account_id),
|
with {:ok, account} <- get_reported_account(data.account_id),
|
||||||
{:ok, {content_html, _, _}} <- make_report_content_html(data["comment"]),
|
{:ok, {content_html, _, _}} <- make_report_content_html(data[:comment]),
|
||||||
{:ok, statuses} <- get_report_statuses(account, data) do
|
{:ok, statuses} <- get_report_statuses(account, data) do
|
||||||
ActivityPub.flag(%{
|
ActivityPub.flag(%{
|
||||||
context: Utils.generate_context_id(),
|
context: Utils.generate_context_id(),
|
||||||
|
@ -392,13 +392,11 @@ def report(user, %{"account_id" => account_id} = data) do
|
||||||
account: account,
|
account: account,
|
||||||
statuses: statuses,
|
statuses: statuses,
|
||||||
content: content_html,
|
content: content_html,
|
||||||
forward: data["forward"] || false
|
forward: Map.get(data, :forward, false)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def report(_user, _params), do: {:error, dgettext("errors", "Valid `account_id` required")}
|
|
||||||
|
|
||||||
defp get_reported_account(account_id) do
|
defp get_reported_account(account_id) do
|
||||||
case User.get_cached_by_id(account_id) do
|
case User.get_cached_by_id(account_id) do
|
||||||
%User{} = account -> {:ok, account}
|
%User{} = account -> {:ok, account}
|
||||||
|
|
|
@ -504,7 +504,8 @@ def make_report_content_html(comment) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_report_statuses(%User{ap_id: actor}, %{"status_ids" => status_ids}) do
|
def get_report_statuses(%User{ap_id: actor}, %{status_ids: status_ids})
|
||||||
|
when is_list(status_ids) do
|
||||||
{:ok, Activity.all_by_actor_and_id(actor, status_ids)}
|
{:ok, Activity.all_by_actor_and_id(actor, status_ids)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,13 @@ defmodule Pleroma.Web.MastodonAPI.ReportController do
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
|
||||||
plug(OAuthScopesPlug, %{scopes: ["write:reports"]} when action == :create)
|
plug(OAuthScopesPlug, %{scopes: ["write:reports"]} when action == :create)
|
||||||
|
|
||||||
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ReportOperation
|
||||||
|
|
||||||
@doc "POST /api/v1/reports"
|
@doc "POST /api/v1/reports"
|
||||||
def create(%{assigns: %{user: user}} = conn, params) do
|
def create(%{assigns: %{user: user}, body_params: params} = conn, _) do
|
||||||
with {:ok, activity} <- Pleroma.Web.CommonAPI.report(user, params) do
|
with {:ok, activity} <- Pleroma.Web.CommonAPI.report(user, params) do
|
||||||
render(conn, "show.json", activity: activity)
|
render(conn, "show.json", activity: activity)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1347,9 +1347,9 @@ test "returns report by its id", %{conn: conn} do
|
||||||
|
|
||||||
{:ok, %{id: report_id}} =
|
{:ok, %{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
response =
|
response =
|
||||||
|
@ -1374,16 +1374,16 @@ test "returns 404 when report id is invalid", %{conn: conn} do
|
||||||
|
|
||||||
{:ok, %{id: report_id}} =
|
{:ok, %{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, %{id: second_report_id}} =
|
{:ok, %{id: second_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel very offended",
|
comment: "I feel very offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
@ -1523,9 +1523,9 @@ test "returns reports", %{conn: conn} do
|
||||||
|
|
||||||
{:ok, %{id: report_id}} =
|
{:ok, %{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
response =
|
response =
|
||||||
|
@ -1547,15 +1547,15 @@ test "returns reports with specified state", %{conn: conn} do
|
||||||
|
|
||||||
{:ok, %{id: first_report_id}} =
|
{:ok, %{id: first_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, %{id: second_report_id}} =
|
{:ok, %{id: second_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I don't like this user"
|
comment: "I don't like this user"
|
||||||
})
|
})
|
||||||
|
|
||||||
CommonAPI.update_report_state(second_report_id, "closed")
|
CommonAPI.update_report_state(second_report_id, "closed")
|
||||||
|
@ -3431,9 +3431,9 @@ test "it resend emails for two users", %{conn: conn, admin: admin} do
|
||||||
|
|
||||||
{:ok, %{id: report_id}} =
|
{:ok, %{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
|
post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
|
||||||
|
|
|
@ -15,7 +15,7 @@ test "renders a report" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.report(user, %{"account_id" => other_user.id})
|
{:ok, activity} = CommonAPI.report(user, %{account_id: other_user.id})
|
||||||
|
|
||||||
expected = %{
|
expected = %{
|
||||||
content: nil,
|
content: nil,
|
||||||
|
@ -48,7 +48,7 @@ test "includes reported statuses" do
|
||||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "toot"})
|
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "toot"})
|
||||||
|
|
||||||
{:ok, report_activity} =
|
{:ok, report_activity} =
|
||||||
CommonAPI.report(user, %{"account_id" => other_user.id, "status_ids" => [activity.id]})
|
CommonAPI.report(user, %{account_id: other_user.id, status_ids: [activity.id]})
|
||||||
|
|
||||||
other_user = Pleroma.User.get_by_id(other_user.id)
|
other_user = Pleroma.User.get_by_id(other_user.id)
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ test "renders report's state" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.report(user, %{"account_id" => other_user.id})
|
{:ok, activity} = CommonAPI.report(user, %{account_id: other_user.id})
|
||||||
{:ok, activity} = CommonAPI.update_report_state(activity.id, "closed")
|
{:ok, activity} = CommonAPI.update_report_state(activity.id, "closed")
|
||||||
|
|
||||||
assert %{state: "closed"} =
|
assert %{state: "closed"} =
|
||||||
|
@ -94,8 +94,8 @@ test "renders report description" do
|
||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity} =
|
||||||
CommonAPI.report(user, %{
|
CommonAPI.report(user, %{
|
||||||
"account_id" => other_user.id,
|
account_id: other_user.id,
|
||||||
"comment" => "posts are too good for this instance"
|
comment: "posts are too good for this instance"
|
||||||
})
|
})
|
||||||
|
|
||||||
assert %{content: "posts are too good for this instance"} =
|
assert %{content: "posts are too good for this instance"} =
|
||||||
|
@ -108,8 +108,8 @@ test "sanitizes report description" do
|
||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity} =
|
||||||
CommonAPI.report(user, %{
|
CommonAPI.report(user, %{
|
||||||
"account_id" => other_user.id,
|
account_id: other_user.id,
|
||||||
"comment" => ""
|
comment: ""
|
||||||
})
|
})
|
||||||
|
|
||||||
data = Map.put(activity.data, "content", "<script> alert('hecked :D:D:D:D:D:D:D') </script>")
|
data = Map.put(activity.data, "content", "<script> alert('hecked :D:D:D:D:D:D:D') </script>")
|
||||||
|
@ -125,8 +125,8 @@ test "doesn't error out when the user doesn't exists" do
|
||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity} =
|
||||||
CommonAPI.report(user, %{
|
CommonAPI.report(user, %{
|
||||||
"account_id" => other_user.id,
|
account_id: other_user.id,
|
||||||
"comment" => ""
|
comment: ""
|
||||||
})
|
})
|
||||||
|
|
||||||
Pleroma.User.delete(other_user)
|
Pleroma.User.delete(other_user)
|
||||||
|
|
|
@ -485,9 +485,9 @@ test "creates a report" do
|
||||||
comment = "foobar"
|
comment = "foobar"
|
||||||
|
|
||||||
report_data = %{
|
report_data = %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => comment,
|
comment: comment,
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
}
|
}
|
||||||
|
|
||||||
note_obj = %{
|
note_obj = %{
|
||||||
|
@ -517,9 +517,9 @@ test "updates report state" do
|
||||||
|
|
||||||
{:ok, %Activity{id: report_id}} =
|
{:ok, %Activity{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
||||||
|
@ -538,9 +538,9 @@ test "does not update report state when state is unsupported" do
|
||||||
|
|
||||||
{:ok, %Activity{id: report_id}} =
|
{:ok, %Activity{id: report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
|
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
|
||||||
|
@ -552,16 +552,16 @@ test "updates state of multiple reports" do
|
||||||
|
|
||||||
{:ok, %Activity{id: first_report_id}} =
|
{:ok, %Activity{id: first_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel offended",
|
comment: "I feel offended",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, %Activity{id: second_report_id}} =
|
{:ok, %Activity{id: second_report_id}} =
|
||||||
CommonAPI.report(reporter, %{
|
CommonAPI.report(reporter, %{
|
||||||
"account_id" => target_user.id,
|
account_id: target_user.id,
|
||||||
"comment" => "I feel very offended!",
|
comment: "I feel very offended!",
|
||||||
"status_ids" => [activity.id]
|
status_ids: [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, report_ids} =
|
{:ok, report_ids} =
|
||||||
|
|
|
@ -22,8 +22,9 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
|
||||||
test "submit a basic report", %{conn: conn, target_user: target_user} do
|
test "submit a basic report", %{conn: conn, target_user: target_user} do
|
||||||
assert %{"action_taken" => false, "id" => _} =
|
assert %{"action_taken" => false, "id" => _} =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "submit a report with statuses and comment", %{
|
test "submit a report with statuses and comment", %{
|
||||||
|
@ -33,23 +34,25 @@ test "submit a report with statuses and comment", %{
|
||||||
} do
|
} do
|
||||||
assert %{"action_taken" => false, "id" => _} =
|
assert %{"action_taken" => false, "id" => _} =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{
|
|> post("/api/v1/reports", %{
|
||||||
"account_id" => target_user.id,
|
"account_id" => target_user.id,
|
||||||
"status_ids" => [activity.id],
|
"status_ids" => [activity.id],
|
||||||
"comment" => "bad status!",
|
"comment" => "bad status!",
|
||||||
"forward" => "false"
|
"forward" => "false"
|
||||||
})
|
})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "account_id is required", %{
|
test "account_id is required", %{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
activity: activity
|
activity: activity
|
||||||
} do
|
} do
|
||||||
assert %{"error" => "Valid `account_id` required"} =
|
assert %{"error" => "Missing field: account_id."} =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{"status_ids" => [activity.id]})
|
|> post("/api/v1/reports", %{"status_ids" => [activity.id]})
|
||||||
|> json_response(400)
|
|> json_response_and_validate_schema(400)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "comment must be up to the size specified in the config", %{
|
test "comment must be up to the size specified in the config", %{
|
||||||
|
@ -63,17 +66,21 @@ test "comment must be up to the size specified in the config", %{
|
||||||
|
|
||||||
assert ^error =
|
assert ^error =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
|
|> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
|
||||||
|> json_response(400)
|
|> json_response_and_validate_schema(400)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns error when account is not exist", %{
|
test "returns error when account is not exist", %{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
activity: activity
|
activity: activity
|
||||||
} do
|
} do
|
||||||
conn = post(conn, "/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
|
||||||
|
|
||||||
assert json_response(conn, 400) == %{"error" => "Account not found"}
|
assert json_response_and_validate_schema(conn, 400) == %{"error" => "Account not found"}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "doesn't fail if an admin has no email", %{conn: conn, target_user: target_user} do
|
test "doesn't fail if an admin has no email", %{conn: conn, target_user: target_user} do
|
||||||
|
@ -81,7 +88,8 @@ test "doesn't fail if an admin has no email", %{conn: conn, target_user: target_
|
||||||
|
|
||||||
assert %{"action_taken" => false, "id" => _} =
|
assert %{"action_taken" => false, "id" => _} =
|
||||||
conn
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue