1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
9 alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
10 alias Pleroma.Web.CommonAPI
13 clear_config(:mrf_simple,
16 federated_timeline_removal: [],
26 describe "when :media_removal" do
28 Config.put([:mrf_simple, :media_removal], [])
29 media_message = build_media_message()
30 local_message = build_local_message()
32 assert SimplePolicy.filter(media_message) == {:ok, media_message}
33 assert SimplePolicy.filter(local_message) == {:ok, local_message}
36 test "has a matching host" do
37 Config.put([:mrf_simple, :media_removal], ["remote.instance"])
38 media_message = build_media_message()
39 local_message = build_local_message()
41 assert SimplePolicy.filter(media_message) ==
44 |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
46 assert SimplePolicy.filter(local_message) == {:ok, local_message}
49 test "match with wildcard domain" do
50 Config.put([:mrf_simple, :media_removal], ["*.remote.instance"])
51 media_message = build_media_message()
52 local_message = build_local_message()
54 assert SimplePolicy.filter(media_message) ==
57 |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
59 assert SimplePolicy.filter(local_message) == {:ok, local_message}
63 describe "when :media_nsfw" do
65 Config.put([:mrf_simple, :media_nsfw], [])
66 media_message = build_media_message()
67 local_message = build_local_message()
69 assert SimplePolicy.filter(media_message) == {:ok, media_message}
70 assert SimplePolicy.filter(local_message) == {:ok, local_message}
73 test "has a matching host" do
74 Config.put([:mrf_simple, :media_nsfw], ["remote.instance"])
75 media_message = build_media_message()
76 local_message = build_local_message()
78 assert SimplePolicy.filter(media_message) ==
81 |> put_in(["object", "tag"], ["foo", "nsfw"])
82 |> put_in(["object", "sensitive"], true)}
84 assert SimplePolicy.filter(local_message) == {:ok, local_message}
87 test "match with wildcard domain" do
88 Config.put([:mrf_simple, :media_nsfw], ["*.remote.instance"])
89 media_message = build_media_message()
90 local_message = build_local_message()
92 assert SimplePolicy.filter(media_message) ==
95 |> put_in(["object", "tag"], ["foo", "nsfw"])
96 |> put_in(["object", "sensitive"], true)}
98 assert SimplePolicy.filter(local_message) == {:ok, local_message}
102 defp build_media_message do
104 "actor" => "https://remote.instance/users/bob",
107 "attachment" => [%{}],
114 describe "when :report_removal" do
116 Config.put([:mrf_simple, :report_removal], [])
117 report_message = build_report_message()
118 local_message = build_local_message()
120 assert SimplePolicy.filter(report_message) == {:ok, report_message}
121 assert SimplePolicy.filter(local_message) == {:ok, local_message}
124 test "has a matching host" do
125 Config.put([:mrf_simple, :report_removal], ["remote.instance"])
126 report_message = build_report_message()
127 local_message = build_local_message()
129 assert {:reject, _} = SimplePolicy.filter(report_message)
130 assert SimplePolicy.filter(local_message) == {:ok, local_message}
133 test "match with wildcard domain" do
134 Config.put([:mrf_simple, :report_removal], ["*.remote.instance"])
135 report_message = build_report_message()
136 local_message = build_local_message()
138 assert {:reject, _} = SimplePolicy.filter(report_message)
139 assert SimplePolicy.filter(local_message) == {:ok, local_message}
143 defp build_report_message do
145 "actor" => "https://remote.instance/users/bob",
150 describe "when :federated_timeline_removal" do
152 Config.put([:mrf_simple, :federated_timeline_removal], [])
153 {_, ftl_message} = build_ftl_actor_and_message()
154 local_message = build_local_message()
156 assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
157 assert SimplePolicy.filter(local_message) == {:ok, local_message}
160 test "has a matching host" do
161 {actor, ftl_message} = build_ftl_actor_and_message()
163 ftl_message_actor_host =
165 |> Map.fetch!("actor")
169 Config.put([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
170 local_message = build_local_message()
172 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
173 assert actor.follower_address in ftl_message["to"]
174 refute actor.follower_address in ftl_message["cc"]
175 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
176 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
178 assert SimplePolicy.filter(local_message) == {:ok, local_message}
181 test "match with wildcard domain" do
182 {actor, ftl_message} = build_ftl_actor_and_message()
184 ftl_message_actor_host =
186 |> Map.fetch!("actor")
190 Config.put([:mrf_simple, :federated_timeline_removal], ["*." <> ftl_message_actor_host])
191 local_message = build_local_message()
193 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
194 assert actor.follower_address in ftl_message["to"]
195 refute actor.follower_address in ftl_message["cc"]
196 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
197 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
199 assert SimplePolicy.filter(local_message) == {:ok, local_message}
202 test "has a matching host but only as:Public in to" do
203 {_actor, ftl_message} = build_ftl_actor_and_message()
205 ftl_message_actor_host =
207 |> Map.fetch!("actor")
211 ftl_message = Map.put(ftl_message, "cc", [])
213 Config.put([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
215 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
216 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
217 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
221 defp build_ftl_actor_and_message do
222 actor = insert(:user)
226 "actor" => actor.ap_id,
227 "to" => ["https://www.w3.org/ns/activitystreams#Public", "http://foo.bar/baz"],
228 "cc" => [actor.follower_address, "http://foo.bar/qux"]
232 describe "when :reject" do
234 Config.put([:mrf_simple, :reject], [])
236 remote_message = build_remote_message()
238 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
241 test "activity has a matching host" do
242 Config.put([:mrf_simple, :reject], ["remote.instance"])
244 remote_message = build_remote_message()
246 assert {:reject, _} = SimplePolicy.filter(remote_message)
249 test "activity matches with wildcard domain" do
250 Config.put([:mrf_simple, :reject], ["*.remote.instance"])
252 remote_message = build_remote_message()
254 assert {:reject, _} = SimplePolicy.filter(remote_message)
257 test "actor has a matching host" do
258 Config.put([:mrf_simple, :reject], ["remote.instance"])
260 remote_user = build_remote_user()
262 assert {:reject, _} = SimplePolicy.filter(remote_user)
266 describe "when :followers_only" do
268 Config.put([:mrf_simple, :followers_only], [])
269 {_, ftl_message} = build_ftl_actor_and_message()
270 local_message = build_local_message()
272 assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
273 assert SimplePolicy.filter(local_message) == {:ok, local_message}
276 test "has a matching host" do
277 actor = insert(:user)
278 following_user = insert(:user)
279 non_following_user = insert(:user)
281 {:ok, _, _, _} = CommonAPI.follow(following_user, actor)
284 "actor" => actor.ap_id,
286 "https://www.w3.org/ns/activitystreams#Public",
287 following_user.ap_id,
288 non_following_user.ap_id
290 "cc" => [actor.follower_address, "http://foo.bar/qux"]
294 "actor" => actor.ap_id,
296 following_user.ap_id,
297 non_following_user.ap_id
304 |> Map.fetch!("actor")
308 Config.put([:mrf_simple, :followers_only], [actor_domain])
310 assert {:ok, new_activity} = SimplePolicy.filter(activity)
311 assert actor.follower_address in new_activity["cc"]
312 assert following_user.ap_id in new_activity["to"]
313 refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["to"]
314 refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["cc"]
315 refute non_following_user.ap_id in new_activity["to"]
316 refute non_following_user.ap_id in new_activity["cc"]
318 assert {:ok, new_dm_activity} = SimplePolicy.filter(dm_activity)
319 assert new_dm_activity["to"] == [following_user.ap_id]
320 assert new_dm_activity["cc"] == []
324 describe "when :accept" do
326 Config.put([:mrf_simple, :accept], [])
328 local_message = build_local_message()
329 remote_message = build_remote_message()
331 assert SimplePolicy.filter(local_message) == {:ok, local_message}
332 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
335 test "is not empty but activity doesn't have a matching host" do
336 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
338 local_message = build_local_message()
339 remote_message = build_remote_message()
341 assert SimplePolicy.filter(local_message) == {:ok, local_message}
342 assert {:reject, _} = SimplePolicy.filter(remote_message)
345 test "activity has a matching host" do
346 Config.put([:mrf_simple, :accept], ["remote.instance"])
348 local_message = build_local_message()
349 remote_message = build_remote_message()
351 assert SimplePolicy.filter(local_message) == {:ok, local_message}
352 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
355 test "activity matches with wildcard domain" do
356 Config.put([:mrf_simple, :accept], ["*.remote.instance"])
358 local_message = build_local_message()
359 remote_message = build_remote_message()
361 assert SimplePolicy.filter(local_message) == {:ok, local_message}
362 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
365 test "actor has a matching host" do
366 Config.put([:mrf_simple, :accept], ["remote.instance"])
368 remote_user = build_remote_user()
370 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
374 describe "when :avatar_removal" do
376 Config.put([:mrf_simple, :avatar_removal], [])
378 remote_user = build_remote_user()
380 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
383 test "is not empty but it doesn't have a matching host" do
384 Config.put([:mrf_simple, :avatar_removal], ["non.matching.remote"])
386 remote_user = build_remote_user()
388 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
391 test "has a matching host" do
392 Config.put([:mrf_simple, :avatar_removal], ["remote.instance"])
394 remote_user = build_remote_user()
395 {:ok, filtered} = SimplePolicy.filter(remote_user)
397 refute filtered["icon"]
400 test "match with wildcard domain" do
401 Config.put([:mrf_simple, :avatar_removal], ["*.remote.instance"])
403 remote_user = build_remote_user()
404 {:ok, filtered} = SimplePolicy.filter(remote_user)
406 refute filtered["icon"]
410 describe "when :banner_removal" do
412 Config.put([:mrf_simple, :banner_removal], [])
414 remote_user = build_remote_user()
416 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
419 test "is not empty but it doesn't have a matching host" do
420 Config.put([:mrf_simple, :banner_removal], ["non.matching.remote"])
422 remote_user = build_remote_user()
424 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
427 test "has a matching host" do
428 Config.put([:mrf_simple, :banner_removal], ["remote.instance"])
430 remote_user = build_remote_user()
431 {:ok, filtered} = SimplePolicy.filter(remote_user)
433 refute filtered["image"]
436 test "match with wildcard domain" do
437 Config.put([:mrf_simple, :banner_removal], ["*.remote.instance"])
439 remote_user = build_remote_user()
440 {:ok, filtered} = SimplePolicy.filter(remote_user)
442 refute filtered["image"]
446 describe "when :reject_deletes is empty" do
447 setup do: Config.put([:mrf_simple, :reject_deletes], [])
449 test "it accepts deletions even from rejected servers" do
450 Config.put([:mrf_simple, :reject], ["remote.instance"])
452 deletion_message = build_remote_deletion_message()
454 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
457 test "it accepts deletions even from non-whitelisted servers" do
458 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
460 deletion_message = build_remote_deletion_message()
462 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
466 describe "when :reject_deletes is not empty but it doesn't have a matching host" do
467 setup do: Config.put([:mrf_simple, :reject_deletes], ["non.matching.remote"])
469 test "it accepts deletions even from rejected servers" do
470 Config.put([:mrf_simple, :reject], ["remote.instance"])
472 deletion_message = build_remote_deletion_message()
474 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
477 test "it accepts deletions even from non-whitelisted servers" do
478 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
480 deletion_message = build_remote_deletion_message()
482 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
486 describe "when :reject_deletes has a matching host" do
487 setup do: Config.put([:mrf_simple, :reject_deletes], ["remote.instance"])
489 test "it rejects the deletion" do
490 deletion_message = build_remote_deletion_message()
492 assert {:reject, _} = SimplePolicy.filter(deletion_message)
496 describe "when :reject_deletes match with wildcard domain" do
497 setup do: Config.put([:mrf_simple, :reject_deletes], ["*.remote.instance"])
499 test "it rejects the deletion" do
500 deletion_message = build_remote_deletion_message()
502 assert {:reject, _} = SimplePolicy.filter(deletion_message)
506 defp build_local_message do
508 "actor" => "#{Pleroma.Web.base_url()}/users/alice",
514 defp build_remote_message do
515 %{"actor" => "https://remote.instance/users/bob"}
518 defp build_remote_user do
520 "id" => "https://remote.instance/users/bob",
522 "url" => "http://example.com/image.jpg",
526 "url" => "http://example.com/image.jpg",
533 defp build_remote_deletion_message do
536 "actor" => "https://remote.instance/users/bob"