eaa595706acf50fc9680a4d0a426321378be40c0
[akkoma] / test / web / activity_pub / mrf / simple_policy_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
6 use Pleroma.DataCase
7 import Pleroma.Factory
8 alias Pleroma.Config
9 alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
10
11 setup do:
12 clear_config(:mrf_simple,
13 media_removal: [],
14 media_nsfw: [],
15 federated_timeline_removal: [],
16 report_removal: [],
17 reject: [],
18 accept: [],
19 avatar_removal: [],
20 banner_removal: []
21 )
22
23 describe "when :media_removal" do
24 test "is empty" do
25 Config.put([:mrf_simple, :media_removal], [])
26 media_message = build_media_message()
27 local_message = build_local_message()
28
29 assert SimplePolicy.filter(media_message) == {:ok, media_message}
30 assert SimplePolicy.filter(local_message) == {:ok, local_message}
31 end
32
33 test "has a matching host" do
34 Config.put([:mrf_simple, :media_removal], ["remote.instance"])
35 media_message = build_media_message()
36 local_message = build_local_message()
37
38 assert SimplePolicy.filter(media_message) ==
39 {:ok,
40 media_message
41 |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
42
43 assert SimplePolicy.filter(local_message) == {:ok, local_message}
44 end
45
46 test "match with wildcard domain" do
47 Config.put([:mrf_simple, :media_removal], ["*.remote.instance"])
48 media_message = build_media_message()
49 local_message = build_local_message()
50
51 assert SimplePolicy.filter(media_message) ==
52 {:ok,
53 media_message
54 |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
55
56 assert SimplePolicy.filter(local_message) == {:ok, local_message}
57 end
58 end
59
60 describe "when :media_nsfw" do
61 test "is empty" do
62 Config.put([:mrf_simple, :media_nsfw], [])
63 media_message = build_media_message()
64 local_message = build_local_message()
65
66 assert SimplePolicy.filter(media_message) == {:ok, media_message}
67 assert SimplePolicy.filter(local_message) == {:ok, local_message}
68 end
69
70 test "has a matching host" do
71 Config.put([:mrf_simple, :media_nsfw], ["remote.instance"])
72 media_message = build_media_message()
73 local_message = build_local_message()
74
75 assert SimplePolicy.filter(media_message) ==
76 {:ok,
77 media_message
78 |> put_in(["object", "tag"], ["foo", "nsfw"])
79 |> put_in(["object", "sensitive"], true)}
80
81 assert SimplePolicy.filter(local_message) == {:ok, local_message}
82 end
83
84 test "match with wildcard domain" do
85 Config.put([:mrf_simple, :media_nsfw], ["*.remote.instance"])
86 media_message = build_media_message()
87 local_message = build_local_message()
88
89 assert SimplePolicy.filter(media_message) ==
90 {:ok,
91 media_message
92 |> put_in(["object", "tag"], ["foo", "nsfw"])
93 |> put_in(["object", "sensitive"], true)}
94
95 assert SimplePolicy.filter(local_message) == {:ok, local_message}
96 end
97 end
98
99 defp build_media_message do
100 %{
101 "actor" => "https://remote.instance/users/bob",
102 "type" => "Create",
103 "object" => %{
104 "attachment" => [%{}],
105 "tag" => ["foo"],
106 "sensitive" => false
107 }
108 }
109 end
110
111 describe "when :report_removal" do
112 test "is empty" do
113 Config.put([:mrf_simple, :report_removal], [])
114 report_message = build_report_message()
115 local_message = build_local_message()
116
117 assert SimplePolicy.filter(report_message) == {:ok, report_message}
118 assert SimplePolicy.filter(local_message) == {:ok, local_message}
119 end
120
121 test "has a matching host" do
122 Config.put([:mrf_simple, :report_removal], ["remote.instance"])
123 report_message = build_report_message()
124 local_message = build_local_message()
125
126 assert SimplePolicy.filter(report_message) == {:reject, nil}
127 assert SimplePolicy.filter(local_message) == {:ok, local_message}
128 end
129
130 test "match with wildcard domain" do
131 Config.put([:mrf_simple, :report_removal], ["*.remote.instance"])
132 report_message = build_report_message()
133 local_message = build_local_message()
134
135 assert SimplePolicy.filter(report_message) == {:reject, nil}
136 assert SimplePolicy.filter(local_message) == {:ok, local_message}
137 end
138 end
139
140 defp build_report_message do
141 %{
142 "actor" => "https://remote.instance/users/bob",
143 "type" => "Flag"
144 }
145 end
146
147 describe "when :federated_timeline_removal" do
148 test "is empty" do
149 Config.put([:mrf_simple, :federated_timeline_removal], [])
150 {_, ftl_message} = build_ftl_actor_and_message()
151 local_message = build_local_message()
152
153 assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
154 assert SimplePolicy.filter(local_message) == {:ok, local_message}
155 end
156
157 test "has a matching host" do
158 {actor, ftl_message} = build_ftl_actor_and_message()
159
160 ftl_message_actor_host =
161 ftl_message
162 |> Map.fetch!("actor")
163 |> URI.parse()
164 |> Map.fetch!(:host)
165
166 Config.put([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
167 local_message = build_local_message()
168
169 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
170 assert actor.follower_address in ftl_message["to"]
171 refute actor.follower_address in ftl_message["cc"]
172 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
173 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
174
175 assert SimplePolicy.filter(local_message) == {:ok, local_message}
176 end
177
178 test "match with wildcard domain" do
179 {actor, ftl_message} = build_ftl_actor_and_message()
180
181 ftl_message_actor_host =
182 ftl_message
183 |> Map.fetch!("actor")
184 |> URI.parse()
185 |> Map.fetch!(:host)
186
187 Config.put([:mrf_simple, :federated_timeline_removal], ["*." <> ftl_message_actor_host])
188 local_message = build_local_message()
189
190 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
191 assert actor.follower_address in ftl_message["to"]
192 refute actor.follower_address in ftl_message["cc"]
193 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
194 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
195
196 assert SimplePolicy.filter(local_message) == {:ok, local_message}
197 end
198
199 test "has a matching host but only as:Public in to" do
200 {_actor, ftl_message} = build_ftl_actor_and_message()
201
202 ftl_message_actor_host =
203 ftl_message
204 |> Map.fetch!("actor")
205 |> URI.parse()
206 |> Map.fetch!(:host)
207
208 ftl_message = Map.put(ftl_message, "cc", [])
209
210 Config.put([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
211
212 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
213 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
214 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
215 end
216 end
217
218 defp build_ftl_actor_and_message do
219 actor = insert(:user)
220
221 {actor,
222 %{
223 "actor" => actor.ap_id,
224 "to" => ["https://www.w3.org/ns/activitystreams#Public", "http://foo.bar/baz"],
225 "cc" => [actor.follower_address, "http://foo.bar/qux"]
226 }}
227 end
228
229 describe "when :reject" do
230 test "is empty" do
231 Config.put([:mrf_simple, :reject], [])
232
233 remote_message = build_remote_message()
234
235 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
236 end
237
238 test "activity has a matching host" do
239 Config.put([:mrf_simple, :reject], ["remote.instance"])
240
241 remote_message = build_remote_message()
242
243 assert SimplePolicy.filter(remote_message) == {:reject, nil}
244 end
245
246 test "activity matches with wildcard domain" do
247 Config.put([:mrf_simple, :reject], ["*.remote.instance"])
248
249 remote_message = build_remote_message()
250
251 assert SimplePolicy.filter(remote_message) == {:reject, nil}
252 end
253
254 test "actor has a matching host" do
255 Config.put([:mrf_simple, :reject], ["remote.instance"])
256
257 remote_user = build_remote_user()
258
259 assert SimplePolicy.filter(remote_user) == {:reject, nil}
260 end
261
262 test "always accept deletions" do
263 Config.put([:mrf_simple, :reject], ["remote.instance"])
264
265 deletion_message = build_remote_deletion_message()
266
267 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
268 end
269 end
270
271 describe "when :accept" do
272 test "is empty" do
273 Config.put([:mrf_simple, :accept], [])
274
275 local_message = build_local_message()
276 remote_message = build_remote_message()
277
278 assert SimplePolicy.filter(local_message) == {:ok, local_message}
279 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
280 end
281
282 test "is not empty but activity doesn't have a matching host" do
283 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
284
285 local_message = build_local_message()
286 remote_message = build_remote_message()
287
288 assert SimplePolicy.filter(local_message) == {:ok, local_message}
289 assert SimplePolicy.filter(remote_message) == {:reject, nil}
290 end
291
292 test "activity has a matching host" do
293 Config.put([:mrf_simple, :accept], ["remote.instance"])
294
295 local_message = build_local_message()
296 remote_message = build_remote_message()
297
298 assert SimplePolicy.filter(local_message) == {:ok, local_message}
299 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
300 end
301
302 test "activity matches with wildcard domain" do
303 Config.put([:mrf_simple, :accept], ["*.remote.instance"])
304
305 local_message = build_local_message()
306 remote_message = build_remote_message()
307
308 assert SimplePolicy.filter(local_message) == {:ok, local_message}
309 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
310 end
311
312 test "actor has a matching host" do
313 Config.put([:mrf_simple, :accept], ["remote.instance"])
314
315 remote_user = build_remote_user()
316
317 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
318 end
319
320 test "always accept deletions" do
321 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
322
323 deletion_message = build_remote_deletion_message()
324
325 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
326 end
327 end
328
329 describe "when :avatar_removal" do
330 test "is empty" do
331 Config.put([:mrf_simple, :avatar_removal], [])
332
333 remote_user = build_remote_user()
334
335 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
336 end
337
338 test "is not empty but it doesn't have a matching host" do
339 Config.put([:mrf_simple, :avatar_removal], ["non.matching.remote"])
340
341 remote_user = build_remote_user()
342
343 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
344 end
345
346 test "has a matching host" do
347 Config.put([:mrf_simple, :avatar_removal], ["remote.instance"])
348
349 remote_user = build_remote_user()
350 {:ok, filtered} = SimplePolicy.filter(remote_user)
351
352 refute filtered["icon"]
353 end
354
355 test "match with wildcard domain" do
356 Config.put([:mrf_simple, :avatar_removal], ["*.remote.instance"])
357
358 remote_user = build_remote_user()
359 {:ok, filtered} = SimplePolicy.filter(remote_user)
360
361 refute filtered["icon"]
362 end
363 end
364
365 describe "when :banner_removal" do
366 test "is empty" do
367 Config.put([:mrf_simple, :banner_removal], [])
368
369 remote_user = build_remote_user()
370
371 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
372 end
373
374 test "is not empty but it doesn't have a matching host" do
375 Config.put([:mrf_simple, :banner_removal], ["non.matching.remote"])
376
377 remote_user = build_remote_user()
378
379 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
380 end
381
382 test "has a matching host" do
383 Config.put([:mrf_simple, :banner_removal], ["remote.instance"])
384
385 remote_user = build_remote_user()
386 {:ok, filtered} = SimplePolicy.filter(remote_user)
387
388 refute filtered["image"]
389 end
390
391 test "match with wildcard domain" do
392 Config.put([:mrf_simple, :banner_removal], ["*.remote.instance"])
393
394 remote_user = build_remote_user()
395 {:ok, filtered} = SimplePolicy.filter(remote_user)
396
397 refute filtered["image"]
398 end
399 end
400
401 defp build_local_message do
402 %{
403 "actor" => "#{Pleroma.Web.base_url()}/users/alice",
404 "to" => [],
405 "cc" => []
406 }
407 end
408
409 defp build_remote_message do
410 %{"actor" => "https://remote.instance/users/bob"}
411 end
412
413 defp build_remote_user do
414 %{
415 "id" => "https://remote.instance/users/bob",
416 "icon" => %{
417 "url" => "http://example.com/image.jpg",
418 "type" => "Image"
419 },
420 "image" => %{
421 "url" => "http://example.com/image.jpg",
422 "type" => "Image"
423 },
424 "type" => "Person"
425 }
426 end
427
428 defp build_remote_deletion_message do
429 %{
430 "type" => "Delete",
431 "actor" => "https://remote.instance/users/bob"
432 }
433 end
434 end