faa35f199032259e341f22dd1caab79064210e61
[anni] / test / pleroma / web / mastodon_api / controllers / filter_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
6   use Pleroma.Web.ConnCase, async: false
7   use Oban.Testing, repo: Pleroma.Repo
8
9   import Mock
10   import Pleroma.Factory
11
12   alias Pleroma.Filter
13   alias Pleroma.Repo
14   alias Pleroma.Workers.PurgeExpiredFilter
15
16   test "non authenticated creation request", %{conn: conn} do
17     response =
18       conn
19       |> put_req_header("content-type", "application/json")
20       |> post("/api/v1/filters", %{"phrase" => "knights", context: ["home"]})
21       |> json_response(403)
22
23     assert response["error"] == "Invalid credentials."
24   end
25
26   describe "creating" do
27     setup do: oauth_access(["write:filters"])
28
29     test "a common filter", %{conn: conn, user: user} do
30       params = %{
31         phrase: "knights",
32         context: ["home"],
33         irreversible: true
34       }
35
36       response =
37         conn
38         |> put_req_header("content-type", "application/json")
39         |> post("/api/v1/filters", params)
40         |> json_response_and_validate_schema(200)
41
42       assert response["phrase"] == params.phrase
43       assert response["context"] == params.context
44       assert response["irreversible"] == true
45       assert response["id"] != nil
46       assert response["id"] != ""
47       assert response["expires_at"] == nil
48
49       filter = Filter.get(response["id"], user)
50       assert filter.hide == true
51     end
52
53     test "a filter with expires_in", %{conn: conn, user: user} do
54       in_seconds = 600
55
56       response =
57         with_mock NaiveDateTime, [:passthrough], utc_now: fn -> ~N[2017-03-17 17:09:58] end do
58           conn
59           |> put_req_header("content-type", "application/json")
60           |> post("/api/v1/filters", %{
61             "phrase" => "knights",
62             context: ["home"],
63             expires_in: in_seconds
64           })
65           |> json_response_and_validate_schema(200)
66         end
67
68       assert response["irreversible"] == false
69       assert response["expires_at"] == "2017-03-17T17:19:58.000Z"
70
71       filter = Filter.get(response["id"], user)
72
73       id = filter.id
74
75       assert_enqueued(
76         worker: PurgeExpiredFilter,
77         args: %{filter_id: filter.id}
78       )
79
80       assert {:ok, %{id: ^id}} =
81                perform_job(PurgeExpiredFilter, %{
82                  filter_id: filter.id
83                })
84
85       assert Repo.aggregate(Filter, :count, :id) == 0
86     end
87   end
88
89   test "fetching a list of filters" do
90     %{user: user, conn: conn} = oauth_access(["read:filters"])
91
92     %{filter_id: id1} = insert(:filter, user: user)
93     %{filter_id: id2} = insert(:filter, user: user)
94
95     id1 = to_string(id1)
96     id2 = to_string(id2)
97
98     assert [%{"id" => ^id2}, %{"id" => ^id1}] =
99              conn
100              |> get("/api/v1/filters")
101              |> json_response_and_validate_schema(200)
102   end
103
104   test "fetching a list of filters without token", %{conn: conn} do
105     insert(:filter)
106
107     response =
108       conn
109       |> get("/api/v1/filters")
110       |> json_response(403)
111
112     assert response["error"] == "Invalid credentials."
113   end
114
115   test "get a filter" do
116     %{user: user, conn: conn} = oauth_access(["read:filters"])
117
118     # check whole_word false
119     filter = insert(:filter, user: user, whole_word: false)
120
121     resp1 =
122       conn |> get("/api/v1/filters/#{filter.filter_id}") |> json_response_and_validate_schema(200)
123
124     assert resp1["whole_word"] == false
125
126     # check whole_word true
127     filter = insert(:filter, user: user, whole_word: true)
128
129     resp2 =
130       conn |> get("/api/v1/filters/#{filter.filter_id}") |> json_response_and_validate_schema(200)
131
132     assert resp2["whole_word"] == true
133   end
134
135   test "get a filter not_found error" do
136     filter = insert(:filter)
137     %{conn: conn} = oauth_access(["read:filters"])
138
139     response =
140       conn |> get("/api/v1/filters/#{filter.filter_id}") |> json_response_and_validate_schema(404)
141
142     assert response["error"] == "Record not found"
143   end
144
145   describe "updating a filter" do
146     setup do: oauth_access(["write:filters"])
147
148     test "common" do
149       %{conn: conn, user: user} = oauth_access(["write:filters"])
150
151       filter =
152         insert(:filter,
153           user: user,
154           hide: true,
155           whole_word: true
156         )
157
158       params = %{
159         phrase: "nii",
160         context: ["public"],
161         irreversible: false
162       }
163
164       response =
165         conn
166         |> put_req_header("content-type", "application/json")
167         |> put("/api/v1/filters/#{filter.filter_id}", params)
168         |> json_response_and_validate_schema(200)
169
170       assert response["phrase"] == params.phrase
171       assert response["context"] == params.context
172       assert response["irreversible"] == false
173       assert response["whole_word"] == true
174     end
175
176     test "with adding expires_at", %{conn: conn, user: user} do
177       filter = insert(:filter, user: user)
178       in_seconds = 600
179
180       response =
181         with_mock NaiveDateTime, [:passthrough], utc_now: fn -> ~N[2017-03-17 17:09:58] end do
182           conn
183           |> put_req_header("content-type", "application/json")
184           |> put("/api/v1/filters/#{filter.filter_id}", %{
185             phrase: "nii",
186             context: ["public"],
187             expires_in: in_seconds,
188             irreversible: true
189           })
190           |> json_response_and_validate_schema(200)
191         end
192
193       assert response["irreversible"] == true
194       assert response["expires_at"] == "2017-03-17T17:19:58.000Z"
195
196       filter = Filter.get(response["id"], user)
197
198       id = filter.id
199
200       assert_enqueued(
201         worker: PurgeExpiredFilter,
202         args: %{filter_id: id}
203       )
204
205       assert {:ok, %{id: ^id}} =
206                perform_job(PurgeExpiredFilter, %{
207                  filter_id: id
208                })
209
210       assert Repo.aggregate(Filter, :count, :id) == 0
211     end
212
213     test "with removing expires_at", %{conn: conn, user: user} do
214       response =
215         conn
216         |> put_req_header("content-type", "application/json")
217         |> post("/api/v1/filters", %{
218           phrase: "cofe",
219           context: ["home"],
220           expires_in: 600
221         })
222         |> json_response_and_validate_schema(200)
223
224       filter = Filter.get(response["id"], user)
225
226       assert_enqueued(
227         worker: PurgeExpiredFilter,
228         args: %{filter_id: filter.id}
229       )
230
231       response =
232         conn
233         |> put_req_header("content-type", "application/json")
234         |> put("/api/v1/filters/#{filter.filter_id}", %{
235           phrase: "nii",
236           context: ["public"],
237           expires_in: nil,
238           whole_word: true
239         })
240         |> json_response_and_validate_schema(200)
241
242       refute_enqueued(
243         worker: PurgeExpiredFilter,
244         args: %{filter_id: filter.id}
245       )
246
247       assert response["irreversible"] == false
248       assert response["whole_word"] == true
249       assert response["expires_at"] == nil
250     end
251
252     test "expires_at is the same in create and update so job is in db", %{conn: conn, user: user} do
253       resp1 =
254         conn
255         |> put_req_header("content-type", "application/json")
256         |> post("/api/v1/filters", %{
257           phrase: "cofe",
258           context: ["home"],
259           expires_in: 600
260         })
261         |> json_response_and_validate_schema(200)
262
263       filter = Filter.get(resp1["id"], user)
264
265       assert_enqueued(
266         worker: PurgeExpiredFilter,
267         args: %{filter_id: filter.id}
268       )
269
270       job = PurgeExpiredFilter.get_expiration(filter.id)
271
272       resp2 =
273         conn
274         |> put_req_header("content-type", "application/json")
275         |> put("/api/v1/filters/#{filter.filter_id}", %{
276           phrase: "nii",
277           context: ["public"]
278         })
279         |> json_response_and_validate_schema(200)
280
281       updated_filter = Filter.get(resp2["id"], user)
282
283       assert_enqueued(
284         worker: PurgeExpiredFilter,
285         args: %{filter_id: updated_filter.id}
286       )
287
288       after_update = PurgeExpiredFilter.get_expiration(updated_filter.id)
289
290       assert resp1["expires_at"] == resp2["expires_at"]
291
292       assert job.scheduled_at == after_update.scheduled_at
293     end
294
295     test "updating expires_at updates oban job too", %{conn: conn, user: user} do
296       resp1 =
297         conn
298         |> put_req_header("content-type", "application/json")
299         |> post("/api/v1/filters", %{
300           phrase: "cofe",
301           context: ["home"],
302           expires_in: 600
303         })
304         |> json_response_and_validate_schema(200)
305
306       filter = Filter.get(resp1["id"], user)
307
308       assert_enqueued(
309         worker: PurgeExpiredFilter,
310         args: %{filter_id: filter.id}
311       )
312
313       job = PurgeExpiredFilter.get_expiration(filter.id)
314
315       resp2 =
316         conn
317         |> put_req_header("content-type", "application/json")
318         |> put("/api/v1/filters/#{filter.filter_id}", %{
319           phrase: "nii",
320           context: ["public"],
321           expires_in: 300
322         })
323         |> json_response_and_validate_schema(200)
324
325       updated_filter = Filter.get(resp2["id"], user)
326
327       assert_enqueued(
328         worker: PurgeExpiredFilter,
329         args: %{filter_id: updated_filter.id}
330       )
331
332       after_update = PurgeExpiredFilter.get_expiration(updated_filter.id)
333
334       refute resp1["expires_at"] == resp2["expires_at"]
335
336       refute job.scheduled_at == after_update.scheduled_at
337     end
338   end
339
340   test "update filter without token", %{conn: conn} do
341     filter = insert(:filter)
342
343     response =
344       conn
345       |> put_req_header("content-type", "application/json")
346       |> put("/api/v1/filters/#{filter.filter_id}", %{
347         phrase: "nii",
348         context: ["public"]
349       })
350       |> json_response(403)
351
352     assert response["error"] == "Invalid credentials."
353   end
354
355   describe "delete a filter" do
356     setup do: oauth_access(["write:filters"])
357
358     test "common", %{conn: conn, user: user} do
359       filter = insert(:filter, user: user)
360
361       assert conn
362              |> delete("/api/v1/filters/#{filter.filter_id}")
363              |> json_response_and_validate_schema(200) == %{}
364
365       assert Repo.all(Filter) == []
366     end
367
368     test "with expires_at", %{conn: conn, user: user} do
369       response =
370         conn
371         |> put_req_header("content-type", "application/json")
372         |> post("/api/v1/filters", %{
373           phrase: "cofe",
374           context: ["home"],
375           expires_in: 600
376         })
377         |> json_response_and_validate_schema(200)
378
379       filter = Filter.get(response["id"], user)
380
381       assert_enqueued(
382         worker: PurgeExpiredFilter,
383         args: %{filter_id: filter.id}
384       )
385
386       assert conn
387              |> delete("/api/v1/filters/#{filter.filter_id}")
388              |> json_response_and_validate_schema(200) == %{}
389
390       refute_enqueued(
391         worker: PurgeExpiredFilter,
392         args: %{filter_id: filter.id}
393       )
394
395       assert Repo.all(Filter) == []
396       assert Repo.all(Oban.Job) == []
397     end
398   end
399
400   test "delete a filter without token", %{conn: conn} do
401     filter = insert(:filter)
402
403     response =
404       conn
405       |> delete("/api/v1/filters/#{filter.filter_id}")
406       |> json_response(403)
407
408     assert response["error"] == "Invalid credentials."
409   end
410 end