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