diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 10d3fe063..cdad6a49b 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1016,6 +1016,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do 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 from(activity in query, where: fragment("?->>'assigned_account' = ?", activity.data, ^assigned_account) @@ -1514,6 +1522,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> restrict_actor(opts) |> restrict_type(opts) |> restrict_state(opts) + |> restrict_report_target(opts) |> restrict_assigned_account(opts) |> restrict_favorited_by(opts) |> restrict_blocked(restrict_blocked_opts) diff --git a/lib/pleroma/web/api_spec/operations/mastodon_admin/account_operation.ex b/lib/pleroma/web/api_spec/operations/mastodon_admin/account_operation.ex index ad79d43d7..3b39cbe2a 100644 --- a/lib/pleroma/web/api_spec/operations/mastodon_admin/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/mastodon_admin/account_operation.ex @@ -216,20 +216,24 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.AccountOperation do properties: %{ type: %Schema{ type: :string, - enum: ["none", "disable", "sensitive", "silence", "suspend"] + enum: ["none", "disable"] }, report_id: %Schema{ type: :string, nullable: true, description: "ID of an associated report that caused this action to be taken" } - } + }, + required: [:type] }, required: true ), responses: %{ 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 diff --git a/lib/pleroma/web/api_spec/operations/mastodon_admin/report_operation.ex b/lib/pleroma/web/api_spec/operations/mastodon_admin/report_operation.ex index f59db9966..7e0bcc24b 100644 --- a/lib/pleroma/web/api_spec/operations/mastodon_admin/report_operation.ex +++ b/lib/pleroma/web/api_spec/operations/mastodon_admin/report_operation.ex @@ -34,7 +34,7 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do :target_account_id, :query, :string, - "Filter by report target account id (not implemented)" + "Filter by report target account id" ) ] ++ pagination_params(), @@ -81,7 +81,8 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do responses: %{ 200 => Operation.response("Report", "application/json", report()), 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 @@ -99,11 +100,43 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do responses: %{ 200 => Operation.response("Report", "application/json", report()), 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 + 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 %Schema{ title: "Admin::Report", @@ -112,7 +145,7 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do id: FlakeID, action_taken: %Schema{type: :boolean}, 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}, forwarded: %Schema{type: :boolean, nullable: true}, created_at: %Schema{type: :string, format: "date-time"}, @@ -136,7 +169,7 @@ defmodule Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation do items: %Schema{ type: :object, properties: %{ - id: %Schema{type: :integer}, + id: %Schema{type: :string}, text: %Schema{type: :string} } } diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex index cb9d521b3..220a8a228 100644 --- a/lib/pleroma/web/common_api.ex +++ b/lib/pleroma/web/common_api.ex @@ -700,7 +700,7 @@ defmodule Pleroma.Web.CommonAPI do end 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) else nil -> {:error, :not_found} @@ -715,7 +715,7 @@ defmodule Pleroma.Web.CommonAPI do end 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) else nil -> {:error, :not_found} diff --git a/lib/pleroma/web/mastodon_api/admin/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/admin/controllers/account_controller.ex index e96566774..b4e038f0e 100644 --- a/lib/pleroma/web/mastodon_api/admin/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/admin/controllers/account_controller.ex @@ -33,6 +33,8 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountController do when action in [:index, :index2, :show] ) + action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + plug( OAuthScopesPlug, %{scopes: ["admin:write:accounts"]} @@ -92,11 +94,18 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountController do conn, _params ) 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) - - json_response(conn, :no_content, "") + {:error, error} -> + json_response(conn, :bad_request, %{error: error}) + end end 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) 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} 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 %{} |> 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 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"), report <- Activity.get_by_id_with_user_actor(activity.id) do ModerationLog.insert_log(%{ @@ -260,9 +296,10 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountController do subject: activity, subject_actor: report.user_actor }) + + :ok end end - defp resolve_report(_admin, _params) do - end + defp resolve_report(_admin, nil), do: :ok end diff --git a/lib/pleroma/web/mastodon_api/admin/controllers/report_controller.ex b/lib/pleroma/web/mastodon_api/admin/controllers/report_controller.ex index 5dbf19aba..062b90fc6 100644 --- a/lib/pleroma/web/mastodon_api/admin/controllers/report_controller.ex +++ b/lib/pleroma/web/mastodon_api/admin/controllers/report_controller.ex @@ -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 [:assign_to_self, :unassign] + ) + + action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MastodonAdmin.ReportOperation def index(conn, params) do @@ -37,6 +44,7 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do |> Map.put(:total, true) |> restrict_state(params) |> restrict_actor(params) + |> restrict_target(params) reports = 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)) else + {:error, :not_found} -> + {:error, :not_found} + {:error, error} -> json_response(conn, :bad_request, %{error: error}) end @@ -84,6 +95,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do render(conn, "show.json", Report.extract_report_info(report)) else + {:error, :not_found} -> + {:error, :not_found} + {:error, error} -> json_response(conn, :bad_request, %{error: error}) end @@ -102,6 +116,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do render(conn, "show.json", Report.extract_report_info(report)) else + {:error, :not_found} -> + {:error, :not_found} + {:error, error} -> json_response(conn, :bad_request, %{error: error}) end @@ -119,14 +136,17 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do render(conn, "show.json", Report.extract_report_info(report)) else + {:error, :not_found} -> + {:error, :not_found} + {:error, error} -> json_response(conn, :bad_request, %{error: error}) 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") @@ -139,4 +159,13 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportController do end 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 diff --git a/lib/pleroma/web/mastodon_api/admin/views/report_view.ex b/lib/pleroma/web/mastodon_api/admin/views/report_view.ex index 664f58b03..088824d03 100644 --- a/lib/pleroma/web/mastodon_api/admin/views/report_view.ex +++ b/lib/pleroma/web/mastodon_api/admin/views/report_view.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportView do use Pleroma.Web, :view alias Pleroma.HTML + alias Pleroma.Rule alias Pleroma.Web.AdminAPI.Report alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.MastodonAPI.Admin.AccountView @@ -21,9 +22,12 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportView do report: report, user: account, account: target_account, - statuses: statuses + statuses: statuses, + assigned_account: assigned_account }) do 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 = unless is_nil(report.data["content"]) do @@ -34,23 +38,34 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportView do %{ id: report.id, - action_taken: report.data["state"] != "open", - action_taken_at: nil, + action_taken: action_taken, + action_taken_at: if(action_taken, do: updated_at), category: "other", comment: content, - forwarded: nil, + forwarded: false, created_at: created_at, - updated_at: created_at, + updated_at: updated_at, account: AccountView.render("show.json", %{user: account}), target_account: AccountView.render("show.json", %{user: target_account}), - assigned_account: nil, + assigned_account: render_account(assigned_account), action_taken_by_account: nil, statuses: StatusView.render("index.json", %{ activities: statuses, as: :activity }), - rules: [] + rules: rules(report.data["rules"]) } 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 diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index aa0ec4817..27229ed41 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -137,6 +137,12 @@ defmodule Pleroma.Web.Router do plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_activation_state) 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 plug(:admin_api) 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 pipe_through([:require_privileged_role_users_manage_activation_state]) - post("/accounts/:id/action", AccountController, :account_action) post("/accounts/:id/enable", AccountController, :enable) 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) scope "/api/v1/admin", Pleroma.Web.MastodonAPI.Admin do pipe_through([:require_privileged_role_users_manage_invites]) @@ -462,6 +473,8 @@ defmodule Pleroma.Web.Router do get("/reports/:id", ReportController, :show) post("/reports/:id/resolve", ReportController, :resolve) post("/reports/:id/reopen", ReportController, :reopen) + post("/reports/:id/assign_to_self", ReportController, :assign_to_self) + post("/reports/:id/unassign", ReportController, :unassign) end # Mastodon AdminAPI: admins and mods (staff) can perform these actions (if privileged by role) diff --git a/test/pleroma/web/mastodon_api/admin/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/admin/controllers/account_controller_test.exs index 113b242dd..38f1189cd 100644 --- a/test/pleroma/web/mastodon_api/admin/controllers/account_controller_test.exs +++ b/test/pleroma/web/mastodon_api/admin/controllers/account_controller_test.exs @@ -183,6 +183,20 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountControllerTest do assert %{is_active: false} = user 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 [reporter, target_user] = insert_pair(:user) @@ -191,11 +205,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountControllerTest do account_id: target_user.id }) - %{id: id} = insert(:user) - conn |> 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", "report_id" => report_id }) @@ -205,6 +217,56 @@ defmodule Pleroma.Web.MastodonAPI.Admin.AccountControllerTest do assert %{data: %{"state" => "resolved"}} = report 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 describe "POST /api/v1/admin/accounts/:id/enable" do diff --git a/test/pleroma/web/mastodon_api/admin/controllers/report_controller_test.exs b/test/pleroma/web/mastodon_api/admin/controllers/report_controller_test.exs index 702dcf1db..2ea5e9d92 100644 --- a/test/pleroma/web/mastodon_api/admin/controllers/report_controller_test.exs +++ b/test/pleroma/web/mastodon_api/admin/controllers/report_controller_test.exs @@ -8,6 +8,9 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportControllerTest do import Pleroma.Factory + alias Pleroma.Activity + alias Pleroma.Repo + alias Pleroma.Rule alias Pleroma.Web.CommonAPI setup_all do @@ -58,6 +61,11 @@ defmodule Pleroma.Web.MastodonAPI.Admin.ReportControllerTest do |> get("/api/v1/admin/reports") |> 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}] = conn |> 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") |> json_response_and_validate_schema(200) 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 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}") |> json_response_and_validate_schema(200) 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 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") |> json_response_and_validate_schema(200) 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 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") |> json_response_and_validate_schema(200) 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