2d526527b2ee8967730b813e80578484b4efd5f8
[akkoma] / test / pleroma / web / admin_api / controllers / report_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
6 use Pleroma.Web.ConnCase, async: true
7
8 import Pleroma.Factory
9
10 alias Pleroma.Activity
11 alias Pleroma.ModerationLog
12 alias Pleroma.Repo
13 alias Pleroma.ReportNote
14 alias Pleroma.Web.CommonAPI
15
16 setup do
17 admin = insert(:user, is_admin: true)
18 token = insert(:oauth_admin_token, user: admin)
19
20 conn =
21 build_conn()
22 |> assign(:user, admin)
23 |> assign(:token, token)
24
25 {:ok, %{admin: admin, token: token, conn: conn}}
26 end
27
28 describe "GET /api/pleroma/admin/reports/:id" do
29 test "returns report by its id", %{conn: conn} do
30 [reporter, target_user] = insert_pair(:user)
31 activity = insert(:note_activity, user: target_user)
32
33 {:ok, %{id: report_id}} =
34 CommonAPI.report(reporter, %{
35 account_id: target_user.id,
36 comment: "I feel offended",
37 status_ids: [activity.id]
38 })
39
40 conn
41 |> put_req_header("content-type", "application/json")
42 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
43 content: "this is an admin note"
44 })
45
46 response =
47 conn
48 |> get("/api/pleroma/admin/reports/#{report_id}")
49 |> json_response_and_validate_schema(:ok)
50
51 assert response["id"] == report_id
52
53 [notes] = response["notes"]
54 assert notes["content"] == "this is an admin note"
55 end
56
57 test "returns 404 when report id is invalid", %{conn: conn} do
58 conn = get(conn, "/api/pleroma/admin/reports/test")
59
60 assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
61 end
62 end
63
64 describe "PATCH /api/pleroma/admin/reports" do
65 setup do
66 [reporter, target_user] = insert_pair(:user)
67 activity = insert(:note_activity, user: target_user)
68
69 {:ok, %{id: report_id}} =
70 CommonAPI.report(reporter, %{
71 account_id: target_user.id,
72 comment: "I feel offended",
73 status_ids: [activity.id]
74 })
75
76 {:ok, %{id: second_report_id}} =
77 CommonAPI.report(reporter, %{
78 account_id: target_user.id,
79 comment: "I feel very offended",
80 status_ids: [activity.id]
81 })
82
83 %{
84 id: report_id,
85 second_report_id: second_report_id
86 }
87 end
88
89 test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} do
90 read_token = insert(:oauth_token, user: admin, scopes: ["admin:read"])
91 write_token = insert(:oauth_token, user: admin, scopes: ["admin:write:reports"])
92
93 response =
94 conn
95 |> assign(:token, read_token)
96 |> put_req_header("content-type", "application/json")
97 |> patch("/api/pleroma/admin/reports", %{
98 "reports" => [%{"state" => "resolved", "id" => id}]
99 })
100 |> json_response_and_validate_schema(403)
101
102 assert response == %{
103 "error" => "Insufficient permissions: admin:write:reports."
104 }
105
106 conn
107 |> assign(:token, write_token)
108 |> put_req_header("content-type", "application/json")
109 |> patch("/api/pleroma/admin/reports", %{
110 "reports" => [%{"state" => "resolved", "id" => id}]
111 })
112 |> json_response_and_validate_schema(:no_content)
113 end
114
115 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
116 conn
117 |> put_req_header("content-type", "application/json")
118 |> patch("/api/pleroma/admin/reports", %{
119 "reports" => [
120 %{"state" => "resolved", "id" => id}
121 ]
122 })
123 |> json_response_and_validate_schema(:no_content)
124
125 activity = Activity.get_by_id_with_user_actor(id)
126 assert activity.data["state"] == "resolved"
127
128 log_entry = Repo.one(ModerationLog)
129
130 assert ModerationLog.get_log_entry_message(log_entry) ==
131 "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'resolved' state"
132 end
133
134 test "closes report", %{conn: conn, id: id, admin: admin} do
135 conn
136 |> put_req_header("content-type", "application/json")
137 |> patch("/api/pleroma/admin/reports", %{
138 "reports" => [
139 %{"state" => "closed", "id" => id}
140 ]
141 })
142 |> json_response_and_validate_schema(:no_content)
143
144 activity = Activity.get_by_id_with_user_actor(id)
145 assert activity.data["state"] == "closed"
146
147 log_entry = Repo.one(ModerationLog)
148
149 assert ModerationLog.get_log_entry_message(log_entry) ==
150 "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'closed' state"
151 end
152
153 test "returns 400 when state is unknown", %{conn: conn, id: id} do
154 conn =
155 conn
156 |> put_req_header("content-type", "application/json")
157 |> patch("/api/pleroma/admin/reports", %{
158 "reports" => [
159 %{"state" => "test", "id" => id}
160 ]
161 })
162
163 assert "Unsupported state" =
164 hd(json_response_and_validate_schema(conn, :bad_request))["error"]
165 end
166
167 test "returns 404 when report is not exist", %{conn: conn} do
168 conn =
169 conn
170 |> put_req_header("content-type", "application/json")
171 |> patch("/api/pleroma/admin/reports", %{
172 "reports" => [
173 %{"state" => "closed", "id" => "test"}
174 ]
175 })
176
177 assert hd(json_response_and_validate_schema(conn, :bad_request))["error"] == "not_found"
178 end
179
180 test "updates state of multiple reports", %{
181 conn: conn,
182 id: id,
183 admin: admin,
184 second_report_id: second_report_id
185 } do
186 conn
187 |> put_req_header("content-type", "application/json")
188 |> patch("/api/pleroma/admin/reports", %{
189 "reports" => [
190 %{"state" => "resolved", "id" => id},
191 %{"state" => "closed", "id" => second_report_id}
192 ]
193 })
194 |> json_response_and_validate_schema(:no_content)
195
196 activity = Activity.get_by_id_with_user_actor(id)
197 second_activity = Activity.get_by_id_with_user_actor(second_report_id)
198 assert activity.data["state"] == "resolved"
199 assert second_activity.data["state"] == "closed"
200
201 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
202
203 assert ModerationLog.get_log_entry_message(first_log_entry) ==
204 "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'resolved' state"
205
206 assert ModerationLog.get_log_entry_message(second_log_entry) ==
207 "@#{admin.nickname} updated report ##{second_report_id} (on user @#{second_activity.user_actor.nickname}) with 'closed' state"
208 end
209 end
210
211 describe "GET /api/pleroma/admin/reports" do
212 test "returns empty response when no reports created", %{conn: conn} do
213 response =
214 conn
215 |> get(report_path(conn, :index))
216 |> json_response_and_validate_schema(:ok)
217
218 assert Enum.empty?(response["reports"])
219 assert response["total"] == 0
220 end
221
222 test "returns reports", %{conn: conn} do
223 [reporter, target_user] = insert_pair(:user)
224 activity = insert(:note_activity, user: target_user)
225
226 {:ok, %{id: report_id}} =
227 CommonAPI.report(reporter, %{
228 account_id: target_user.id,
229 comment: "I feel offended",
230 status_ids: [activity.id]
231 })
232
233 response =
234 conn
235 |> get(report_path(conn, :index))
236 |> json_response_and_validate_schema(:ok)
237
238 [report] = response["reports"]
239
240 assert length(response["reports"]) == 1
241 assert report["id"] == report_id
242
243 assert response["total"] == 1
244 end
245
246 test "returns reports with specified state", %{conn: conn} do
247 [reporter, target_user] = insert_pair(:user)
248 activity = insert(:note_activity, user: target_user)
249
250 {:ok, %{id: first_report_id}} =
251 CommonAPI.report(reporter, %{
252 account_id: target_user.id,
253 comment: "I feel offended",
254 status_ids: [activity.id]
255 })
256
257 {:ok, %{id: second_report_id}} =
258 CommonAPI.report(reporter, %{
259 account_id: target_user.id,
260 comment: "I don't like this user"
261 })
262
263 CommonAPI.update_report_state(second_report_id, "closed")
264
265 response =
266 conn
267 |> get(report_path(conn, :index, %{state: "open"}))
268 |> json_response_and_validate_schema(:ok)
269
270 assert [open_report] = response["reports"]
271
272 assert length(response["reports"]) == 1
273 assert open_report["id"] == first_report_id
274
275 assert response["total"] == 1
276
277 response =
278 conn
279 |> get(report_path(conn, :index, %{state: "closed"}))
280 |> json_response_and_validate_schema(:ok)
281
282 assert [closed_report] = response["reports"]
283
284 assert length(response["reports"]) == 1
285 assert closed_report["id"] == second_report_id
286
287 assert response["total"] == 1
288
289 assert %{"total" => 0, "reports" => []} ==
290 conn
291 |> get(report_path(conn, :index, %{state: "resolved"}))
292 |> json_response_and_validate_schema(:ok)
293 end
294
295 test "returns 403 when requested by a non-admin" do
296 user = insert(:user)
297 token = insert(:oauth_token, user: user)
298
299 conn =
300 build_conn()
301 |> assign(:user, user)
302 |> assign(:token, token)
303 |> get("/api/pleroma/admin/reports")
304
305 assert json_response(conn, :forbidden) ==
306 %{"error" => "User is not a staff member."}
307 end
308
309 test "returns 403 when requested by anonymous" do
310 conn = get(build_conn(), "/api/pleroma/admin/reports")
311
312 assert json_response(conn, :forbidden) == %{
313 "error" => "Invalid credentials."
314 }
315 end
316 end
317
318 describe "POST /api/pleroma/admin/reports/:id/notes" do
319 setup %{conn: conn, admin: admin} do
320 [reporter, target_user] = insert_pair(:user)
321 activity = insert(:note_activity, user: target_user)
322
323 {:ok, %{id: report_id}} =
324 CommonAPI.report(reporter, %{
325 account_id: target_user.id,
326 comment: "I feel offended",
327 status_ids: [activity.id]
328 })
329
330 conn
331 |> put_req_header("content-type", "application/json")
332 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
333 content: "this is disgusting!"
334 })
335
336 conn
337 |> put_req_header("content-type", "application/json")
338 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
339 content: "this is disgusting2!"
340 })
341
342 %{
343 admin_id: admin.id,
344 report_id: report_id
345 }
346 end
347
348 test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
349 assert [note, _] = Repo.all(ReportNote)
350
351 assert %{
352 activity_id: ^report_id,
353 content: "this is disgusting!",
354 user_id: ^admin_id
355 } = note
356 end
357
358 test "it returns reports with notes", %{conn: conn, admin: admin} do
359 conn = get(conn, "/api/pleroma/admin/reports")
360
361 response = json_response_and_validate_schema(conn, 200)
362 notes = hd(response["reports"])["notes"]
363 assert 2 == Enum.count(notes)
364
365 note =
366 notes
367 |> Enum.find(fn note -> note["content"] == "this is disgusting!" end)
368
369 refute is_nil(note)
370
371 assert note["user"]["nickname"] == admin.nickname
372 # We use '=~' because the order of the notes isn't guaranteed
373 assert note["content"] =~ "this is disgusting"
374 assert note["created_at"]
375 assert response["total"] == 1
376 end
377
378 test "it deletes the note", %{conn: conn, report_id: report_id} do
379 assert ReportNote |> Repo.all() |> length() == 2
380 assert [note, _] = Repo.all(ReportNote)
381
382 delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
383
384 assert ReportNote |> Repo.all() |> length() == 1
385 end
386 end
387 end