91c24c2d96fac2a31fabb75ef48bc1ec8a7e5808
[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 end
262
263 describe "when :accept" do
264 test "is empty" do
265 Config.put([:mrf_simple, :accept], [])
266
267 local_message = build_local_message()
268 remote_message = build_remote_message()
269
270 assert SimplePolicy.filter(local_message) == {:ok, local_message}
271 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
272 end
273
274 test "is not empty but activity doesn't have a matching host" do
275 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
276
277 local_message = build_local_message()
278 remote_message = build_remote_message()
279
280 assert SimplePolicy.filter(local_message) == {:ok, local_message}
281 assert SimplePolicy.filter(remote_message) == {:reject, nil}
282 end
283
284 test "activity has a matching host" do
285 Config.put([:mrf_simple, :accept], ["remote.instance"])
286
287 local_message = build_local_message()
288 remote_message = build_remote_message()
289
290 assert SimplePolicy.filter(local_message) == {:ok, local_message}
291 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
292 end
293
294 test "activity matches with wildcard domain" do
295 Config.put([:mrf_simple, :accept], ["*.remote.instance"])
296
297 local_message = build_local_message()
298 remote_message = build_remote_message()
299
300 assert SimplePolicy.filter(local_message) == {:ok, local_message}
301 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
302 end
303
304 test "actor has a matching host" do
305 Config.put([:mrf_simple, :accept], ["remote.instance"])
306
307 remote_user = build_remote_user()
308
309 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
310 end
311 end
312
313 describe "when :avatar_removal" do
314 test "is empty" do
315 Config.put([:mrf_simple, :avatar_removal], [])
316
317 remote_user = build_remote_user()
318
319 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
320 end
321
322 test "is not empty but it doesn't have a matching host" do
323 Config.put([:mrf_simple, :avatar_removal], ["non.matching.remote"])
324
325 remote_user = build_remote_user()
326
327 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
328 end
329
330 test "has a matching host" do
331 Config.put([:mrf_simple, :avatar_removal], ["remote.instance"])
332
333 remote_user = build_remote_user()
334 {:ok, filtered} = SimplePolicy.filter(remote_user)
335
336 refute filtered["icon"]
337 end
338
339 test "match with wildcard domain" do
340 Config.put([:mrf_simple, :avatar_removal], ["*.remote.instance"])
341
342 remote_user = build_remote_user()
343 {:ok, filtered} = SimplePolicy.filter(remote_user)
344
345 refute filtered["icon"]
346 end
347 end
348
349 describe "when :banner_removal" do
350 test "is empty" do
351 Config.put([:mrf_simple, :banner_removal], [])
352
353 remote_user = build_remote_user()
354
355 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
356 end
357
358 test "is not empty but it doesn't have a matching host" do
359 Config.put([:mrf_simple, :banner_removal], ["non.matching.remote"])
360
361 remote_user = build_remote_user()
362
363 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
364 end
365
366 test "has a matching host" do
367 Config.put([:mrf_simple, :banner_removal], ["remote.instance"])
368
369 remote_user = build_remote_user()
370 {:ok, filtered} = SimplePolicy.filter(remote_user)
371
372 refute filtered["image"]
373 end
374
375 test "match with wildcard domain" do
376 Config.put([:mrf_simple, :banner_removal], ["*.remote.instance"])
377
378 remote_user = build_remote_user()
379 {:ok, filtered} = SimplePolicy.filter(remote_user)
380
381 refute filtered["image"]
382 end
383 end
384
385 defp build_local_message do
386 %{
387 "actor" => "#{Pleroma.Web.base_url()}/users/alice",
388 "to" => [],
389 "cc" => []
390 }
391 end
392
393 defp build_remote_message do
394 %{"actor" => "https://remote.instance/users/bob"}
395 end
396
397 defp build_remote_user do
398 %{
399 "id" => "https://remote.instance/users/bob",
400 "icon" => %{
401 "url" => "http://example.com/image.jpg",
402 "type" => "Image"
403 },
404 "image" => %{
405 "url" => "http://example.com/image.jpg",
406 "type" => "Image"
407 },
408 "type" => "Person"
409 }
410 end
411 end