1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
6 use Pleroma.Web.ConnCase, async: false
10 alias Pleroma.Activity
11 alias Pleroma.ModerationLog
13 alias Pleroma.ReportNote
14 alias Pleroma.Web.CommonAPI
17 admin = insert(:user, is_admin: true)
18 token = insert(:oauth_admin_token, user: admin)
22 |> assign(:user, admin)
23 |> assign(:token, token)
25 {:ok, %{admin: admin, token: token, conn: conn}}
28 describe "GET /api/pleroma/admin/reports/:id" do
30 clear_config([:instance, :admin_privileges], [:reports_manage_reports])
33 test "returns 403 if not privileged with :reports_manage_reports", %{conn: conn} do
34 clear_config([:instance, :admin_privileges], [])
38 |> get("/api/pleroma/admin/reports/report_id")
40 assert json_response(conn, :forbidden)
43 test "returns report by its id", %{conn: conn} do
44 [reporter, target_user] = insert_pair(:user)
45 activity = insert(:note_activity, user: target_user)
47 {:ok, %{id: report_id}} =
48 CommonAPI.report(reporter, %{
49 account_id: target_user.id,
50 comment: "I feel offended",
51 status_ids: [activity.id]
55 |> put_req_header("content-type", "application/json")
56 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
57 content: "this is an admin note"
62 |> get("/api/pleroma/admin/reports/#{report_id}")
63 |> json_response_and_validate_schema(:ok)
65 assert response["id"] == report_id
67 [notes] = response["notes"]
68 assert notes["content"] == "this is an admin note"
71 test "renders reported content even if the status is deleted", %{conn: conn} do
72 [reporter, target_user] = insert_pair(:user)
73 activity = insert(:note_activity, user: target_user)
74 activity = Activity.normalize(activity)
76 {:ok, %{id: report_id}} =
77 CommonAPI.report(reporter, %{
78 account_id: target_user.id,
79 comment: "I feel offended",
80 status_ids: [activity.id]
83 CommonAPI.delete(activity.id, target_user)
87 |> get("/api/pleroma/admin/reports/#{report_id}")
88 |> json_response_and_validate_schema(:ok)
90 assert response["id"] == report_id
92 assert [status] = response["statuses"]
93 assert activity.object.data["id"] == status["uri"]
94 assert activity.object.data["content"] == status["content"]
97 test "returns 404 when report id is invalid", %{conn: conn} do
98 conn = get(conn, "/api/pleroma/admin/reports/test")
100 assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
104 describe "PATCH /api/pleroma/admin/reports" do
106 clear_config([:instance, :admin_privileges], [:reports_manage_reports])
108 [reporter, target_user] = insert_pair(:user)
109 activity = insert(:note_activity, user: target_user)
111 {:ok, %{id: report_id}} =
112 CommonAPI.report(reporter, %{
113 account_id: target_user.id,
114 comment: "I feel offended",
115 status_ids: [activity.id]
118 {:ok, %{id: second_report_id}} =
119 CommonAPI.report(reporter, %{
120 account_id: target_user.id,
121 comment: "I feel very offended",
122 status_ids: [activity.id]
128 second_report_id: second_report_id
132 test "returns 403 if not privileged with :reports_manage_reports", %{
137 clear_config([:instance, :admin_privileges], [])
141 |> assign(:token, insert(:oauth_token, user: admin, scopes: ["admin:write:reports"]))
142 |> put_req_header("content-type", "application/json")
143 |> patch("/api/pleroma/admin/reports", %{
144 "reports" => [%{"state" => "resolved", "id" => id}]
147 assert json_response(conn, :forbidden)
150 test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} do
151 read_token = insert(:oauth_token, user: admin, scopes: ["admin:read"])
152 write_token = insert(:oauth_token, user: admin, scopes: ["admin:write:reports"])
156 |> assign(:token, read_token)
157 |> put_req_header("content-type", "application/json")
158 |> patch("/api/pleroma/admin/reports", %{
159 "reports" => [%{"state" => "resolved", "id" => id}]
161 |> json_response_and_validate_schema(403)
163 assert response == %{
164 "error" => "Insufficient permissions: admin:write:reports."
168 |> assign(:token, write_token)
169 |> put_req_header("content-type", "application/json")
170 |> patch("/api/pleroma/admin/reports", %{
171 "reports" => [%{"state" => "resolved", "id" => id}]
173 |> json_response_and_validate_schema(:no_content)
176 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
178 |> put_req_header("content-type", "application/json")
179 |> patch("/api/pleroma/admin/reports", %{
181 %{"state" => "resolved", "id" => id}
184 |> json_response_and_validate_schema(:no_content)
186 activity = Activity.get_by_id_with_user_actor(id)
187 assert activity.data["state"] == "resolved"
189 log_entry = Repo.one(ModerationLog)
191 assert ModerationLog.get_log_entry_message(log_entry) ==
192 "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'resolved' state"
195 test "closes report", %{conn: conn, id: id, admin: admin} do
197 |> put_req_header("content-type", "application/json")
198 |> patch("/api/pleroma/admin/reports", %{
200 %{"state" => "closed", "id" => id}
203 |> json_response_and_validate_schema(:no_content)
205 activity = Activity.get_by_id_with_user_actor(id)
206 assert activity.data["state"] == "closed"
208 log_entry = Repo.one(ModerationLog)
210 assert ModerationLog.get_log_entry_message(log_entry) ==
211 "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'closed' state"
214 test "returns 400 when state is unknown", %{conn: conn, id: id} do
217 |> put_req_header("content-type", "application/json")
218 |> patch("/api/pleroma/admin/reports", %{
220 %{"state" => "test", "id" => id}
224 assert "Unsupported state" =
225 hd(json_response_and_validate_schema(conn, :bad_request))["error"]
228 test "returns 404 when report is not exist", %{conn: conn} do
231 |> put_req_header("content-type", "application/json")
232 |> patch("/api/pleroma/admin/reports", %{
234 %{"state" => "closed", "id" => "test"}
238 assert hd(json_response_and_validate_schema(conn, :bad_request))["error"] == "not_found"
241 test "updates state of multiple reports", %{
245 second_report_id: second_report_id
248 |> put_req_header("content-type", "application/json")
249 |> patch("/api/pleroma/admin/reports", %{
251 %{"state" => "resolved", "id" => id},
252 %{"state" => "closed", "id" => second_report_id}
255 |> json_response_and_validate_schema(:no_content)
257 activity = Activity.get_by_id_with_user_actor(id)
258 second_activity = Activity.get_by_id_with_user_actor(second_report_id)
259 assert activity.data["state"] == "resolved"
260 assert second_activity.data["state"] == "closed"
262 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
264 assert ModerationLog.get_log_entry_message(first_log_entry) ==
265 "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'resolved' state"
267 assert ModerationLog.get_log_entry_message(second_log_entry) ==
268 "@#{admin.nickname} updated report ##{second_report_id} (on user @#{second_activity.user_actor.nickname}) with 'closed' state"
271 test "works if reporter is deactivated", %{
276 Pleroma.User.set_activation(reporter, false)
279 |> put_req_header("content-type", "application/json")
280 |> patch("/api/pleroma/admin/reports", %{
282 %{"state" => "resolved", "id" => id}
285 |> json_response_and_validate_schema(:no_content)
287 activity = Activity.get_by_id_with_user_actor(id)
288 assert activity.data["state"] == "resolved"
292 describe "GET /api/pleroma/admin/reports" do
294 clear_config([:instance, :admin_privileges], [:reports_manage_reports])
297 test "returns 403 if not privileged with :reports_manage_reports", %{conn: conn} do
298 clear_config([:instance, :admin_privileges], [])
302 |> get(report_path(conn, :index))
304 assert json_response(conn, :forbidden)
307 test "returns empty response when no reports created", %{conn: conn} do
310 |> get(report_path(conn, :index))
311 |> json_response_and_validate_schema(:ok)
313 assert Enum.empty?(response["reports"])
314 assert response["total"] == 0
317 test "returns reports", %{conn: conn} do
318 [reporter, target_user] = insert_pair(:user)
319 activity = insert(:note_activity, user: target_user)
321 {:ok, %{id: report_id}} =
322 CommonAPI.report(reporter, %{
323 account_id: target_user.id,
324 comment: "I feel offended",
325 status_ids: [activity.id]
330 |> get(report_path(conn, :index))
331 |> json_response_and_validate_schema(:ok)
333 [report] = response["reports"]
335 assert length(response["reports"]) == 1
336 assert report["id"] == report_id
338 assert response["total"] == 1
341 test "returns reports with specified state", %{conn: conn} do
342 [reporter, target_user] = insert_pair(:user)
343 activity = insert(:note_activity, user: target_user)
345 {:ok, %{id: first_report_id}} =
346 CommonAPI.report(reporter, %{
347 account_id: target_user.id,
348 comment: "I feel offended",
349 status_ids: [activity.id]
352 {:ok, %{id: second_report_id}} =
353 CommonAPI.report(reporter, %{
354 account_id: target_user.id,
355 comment: "I don't like this user"
358 CommonAPI.update_report_state(second_report_id, "closed")
362 |> get(report_path(conn, :index, %{state: "open"}))
363 |> json_response_and_validate_schema(:ok)
365 assert [open_report] = response["reports"]
367 assert length(response["reports"]) == 1
368 assert open_report["id"] == first_report_id
370 assert response["total"] == 1
374 |> get(report_path(conn, :index, %{state: "closed"}))
375 |> json_response_and_validate_schema(:ok)
377 assert [closed_report] = response["reports"]
379 assert length(response["reports"]) == 1
380 assert closed_report["id"] == second_report_id
382 assert response["total"] == 1
384 assert %{"total" => 0, "reports" => []} ==
386 |> get(report_path(conn, :index, %{state: "resolved"}))
387 |> json_response_and_validate_schema(:ok)
390 test "renders content correctly", %{conn: conn} do
391 [reporter, target_user] = insert_pair(:user)
392 note = insert(:note, user: target_user, data: %{"content" => "mew 1"})
393 note2 = insert(:note, user: target_user, data: %{"content" => "mew 2"})
394 activity = insert(:note_activity, user: target_user, note: note)
395 activity2 = insert(:note_activity, user: target_user, note: note2)
398 CommonAPI.report(reporter, %{
399 account_id: target_user.id,
400 comment: "I feel offended",
401 status_ids: [activity.id, activity2.id]
404 CommonAPI.delete(activity.id, target_user)
405 CommonAPI.delete(activity2.id, target_user)
409 |> get(report_path(conn, :index))
410 |> json_response_and_validate_schema(:ok)
412 assert [open_report] = response["reports"]
413 assert %{"statuses" => [s1, s2]} = open_report
414 assert "mew 1" in [s1["content"], s2["content"]]
415 assert "mew 2" in [s1["content"], s2["content"]]
418 test "returns 403 when requested by a non-admin" do
420 token = insert(:oauth_token, user: user)
424 |> assign(:user, user)
425 |> assign(:token, token)
426 |> get("/api/pleroma/admin/reports")
428 assert json_response(conn, :forbidden) ==
429 %{"error" => "User is not a staff member."}
432 test "returns 403 when requested by anonymous" do
433 conn = get(build_conn(), "/api/pleroma/admin/reports")
435 assert json_response(conn, :forbidden) == %{
436 "error" => "Invalid credentials."
441 describe "POST /api/pleroma/admin/reports/:id/notes" do
442 setup %{conn: conn, admin: admin} do
443 clear_config([:instance, :admin_privileges], [:reports_manage_reports])
445 [reporter, target_user] = insert_pair(:user)
446 activity = insert(:note_activity, user: target_user)
448 {:ok, %{id: report_id}} =
449 CommonAPI.report(reporter, %{
450 account_id: target_user.id,
451 comment: "I feel offended",
452 status_ids: [activity.id]
456 |> put_req_header("content-type", "application/json")
457 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
458 content: "this is disgusting!"
462 |> put_req_header("content-type", "application/json")
463 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
464 content: "this is disgusting2!"
473 test "returns 403 if not privileged with :reports_manage_reports", %{
477 clear_config([:instance, :admin_privileges], [])
481 |> put_req_header("content-type", "application/json")
482 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
483 content: "this is disgusting2!"
486 delete_conn = delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/note.id")
488 assert json_response(post_conn, :forbidden)
489 assert json_response(delete_conn, :forbidden)
492 test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
493 assert [note, _] = Repo.all(ReportNote)
496 activity_id: ^report_id,
497 content: "this is disgusting!",
502 test "it returns reports with notes", %{conn: conn, admin: admin} do
503 conn = get(conn, "/api/pleroma/admin/reports")
505 response = json_response_and_validate_schema(conn, 200)
506 notes = hd(response["reports"])["notes"]
509 assert note["user"]["nickname"] == admin.nickname
510 # We use '=~' because the order of the notes isn't guaranteed
511 assert note["content"] =~ "this is disgusting"
512 assert note["created_at"]
513 assert response["total"] == 1
516 test "it deletes the note", %{conn: conn, report_id: report_id} do
517 assert ReportNote |> Repo.all() |> length() == 2
518 assert [note, _] = Repo.all(ReportNote)
520 delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
522 assert ReportNote |> Repo.all() |> length() == 1