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
8 alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
9 alias Pleroma.Web.CommonAPI
12 clear_config(:mrf_simple,
15 federated_timeline_removal: [],
25 describe "when :media_removal" do
27 clear_config([:mrf_simple, :media_removal], [])
28 media_message = build_media_message()
29 local_message = build_local_message()
31 assert SimplePolicy.filter(media_message) == {:ok, media_message}
32 assert SimplePolicy.filter(local_message) == {:ok, local_message}
35 test "has a matching host" do
36 clear_config([:mrf_simple, :media_removal], ["remote.instance"])
37 media_message = build_media_message()
38 local_message = build_local_message()
40 assert SimplePolicy.filter(media_message) ==
43 |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
45 assert SimplePolicy.filter(local_message) == {:ok, local_message}
48 test "match with wildcard domain" do
49 clear_config([:mrf_simple, :media_removal], ["*.remote.instance"])
50 media_message = build_media_message()
51 local_message = build_local_message()
53 assert SimplePolicy.filter(media_message) ==
56 |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
58 assert SimplePolicy.filter(local_message) == {:ok, local_message}
62 describe "when :media_nsfw" do
64 clear_config([:mrf_simple, :media_nsfw], [])
65 media_message = build_media_message()
66 local_message = build_local_message()
68 assert SimplePolicy.filter(media_message) == {:ok, media_message}
69 assert SimplePolicy.filter(local_message) == {:ok, local_message}
72 test "has a matching host" do
73 clear_config([:mrf_simple, :media_nsfw], ["remote.instance"])
74 media_message = build_media_message()
75 local_message = build_local_message()
77 assert SimplePolicy.filter(media_message) ==
80 |> put_in(["object", "tag"], ["foo", "nsfw"])
81 |> put_in(["object", "sensitive"], true)}
83 assert SimplePolicy.filter(local_message) == {:ok, local_message}
86 test "match with wildcard domain" do
87 clear_config([:mrf_simple, :media_nsfw], ["*.remote.instance"])
88 media_message = build_media_message()
89 local_message = build_local_message()
91 assert SimplePolicy.filter(media_message) ==
94 |> put_in(["object", "tag"], ["foo", "nsfw"])
95 |> put_in(["object", "sensitive"], true)}
97 assert SimplePolicy.filter(local_message) == {:ok, local_message}
101 defp build_media_message do
103 "actor" => "https://remote.instance/users/bob",
106 "attachment" => [%{}],
113 describe "when :report_removal" do
115 clear_config([:mrf_simple, :report_removal], [])
116 report_message = build_report_message()
117 local_message = build_local_message()
119 assert SimplePolicy.filter(report_message) == {:ok, report_message}
120 assert SimplePolicy.filter(local_message) == {:ok, local_message}
123 test "has a matching host" do
124 clear_config([:mrf_simple, :report_removal], ["remote.instance"])
125 report_message = build_report_message()
126 local_message = build_local_message()
128 assert {:reject, _} = SimplePolicy.filter(report_message)
129 assert SimplePolicy.filter(local_message) == {:ok, local_message}
132 test "match with wildcard domain" do
133 clear_config([:mrf_simple, :report_removal], ["*.remote.instance"])
134 report_message = build_report_message()
135 local_message = build_local_message()
137 assert {:reject, _} = SimplePolicy.filter(report_message)
138 assert SimplePolicy.filter(local_message) == {:ok, local_message}
142 defp build_report_message do
144 "actor" => "https://remote.instance/users/bob",
149 describe "when :federated_timeline_removal" do
151 clear_config([:mrf_simple, :federated_timeline_removal], [])
152 {_, ftl_message} = build_ftl_actor_and_message()
153 local_message = build_local_message()
155 assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
156 assert SimplePolicy.filter(local_message) == {:ok, local_message}
159 test "has a matching host" do
160 {actor, ftl_message} = build_ftl_actor_and_message()
162 ftl_message_actor_host =
164 |> Map.fetch!("actor")
168 clear_config([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
169 local_message = build_local_message()
171 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
172 assert actor.follower_address in ftl_message["to"]
173 refute actor.follower_address in ftl_message["cc"]
174 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
175 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
177 assert SimplePolicy.filter(local_message) == {:ok, local_message}
180 test "match with wildcard domain" do
181 {actor, ftl_message} = build_ftl_actor_and_message()
183 ftl_message_actor_host =
185 |> Map.fetch!("actor")
189 clear_config([:mrf_simple, :federated_timeline_removal], ["*." <> ftl_message_actor_host])
190 local_message = build_local_message()
192 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
193 assert actor.follower_address in ftl_message["to"]
194 refute actor.follower_address in ftl_message["cc"]
195 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
196 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
198 assert SimplePolicy.filter(local_message) == {:ok, local_message}
201 test "has a matching host but only as:Public in to" do
202 {_actor, ftl_message} = build_ftl_actor_and_message()
204 ftl_message_actor_host =
206 |> Map.fetch!("actor")
210 ftl_message = Map.put(ftl_message, "cc", [])
212 clear_config([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
214 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
215 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
216 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
220 defp build_ftl_actor_and_message do
221 actor = insert(:user)
225 "actor" => actor.ap_id,
226 "to" => ["https://www.w3.org/ns/activitystreams#Public", "http://foo.bar/baz"],
227 "cc" => [actor.follower_address, "http://foo.bar/qux"]
231 describe "when :reject" do
233 clear_config([:mrf_simple, :reject], [])
235 remote_message = build_remote_message()
237 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
240 test "activity has a matching host" do
241 clear_config([:mrf_simple, :reject], ["remote.instance"])
243 remote_message = build_remote_message()
245 assert {:reject, _} = SimplePolicy.filter(remote_message)
248 test "activity matches with wildcard domain" do
249 clear_config([:mrf_simple, :reject], ["*.remote.instance"])
251 remote_message = build_remote_message()
253 assert {:reject, _} = SimplePolicy.filter(remote_message)
256 test "actor has a matching host" do
257 clear_config([:mrf_simple, :reject], ["remote.instance"])
259 remote_user = build_remote_user()
261 assert {:reject, _} = SimplePolicy.filter(remote_user)
265 describe "when :followers_only" do
267 clear_config([:mrf_simple, :followers_only], [])
268 {_, ftl_message} = build_ftl_actor_and_message()
269 local_message = build_local_message()
271 assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
272 assert SimplePolicy.filter(local_message) == {:ok, local_message}
275 test "has a matching host" do
276 actor = insert(:user)
277 following_user = insert(:user)
278 non_following_user = insert(:user)
280 {:ok, _, _, _} = CommonAPI.follow(following_user, actor)
283 "actor" => actor.ap_id,
285 "https://www.w3.org/ns/activitystreams#Public",
286 following_user.ap_id,
287 non_following_user.ap_id
289 "cc" => [actor.follower_address, "http://foo.bar/qux"]
293 "actor" => actor.ap_id,
295 following_user.ap_id,
296 non_following_user.ap_id
303 |> Map.fetch!("actor")
307 clear_config([:mrf_simple, :followers_only], [actor_domain])
309 assert {:ok, new_activity} = SimplePolicy.filter(activity)
310 assert actor.follower_address in new_activity["cc"]
311 assert following_user.ap_id in new_activity["to"]
312 refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["to"]
313 refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["cc"]
314 refute non_following_user.ap_id in new_activity["to"]
315 refute non_following_user.ap_id in new_activity["cc"]
317 assert {:ok, new_dm_activity} = SimplePolicy.filter(dm_activity)
318 assert new_dm_activity["to"] == [following_user.ap_id]
319 assert new_dm_activity["cc"] == []
323 describe "when :accept" do
325 clear_config([:mrf_simple, :accept], [])
327 local_message = build_local_message()
328 remote_message = build_remote_message()
330 assert SimplePolicy.filter(local_message) == {:ok, local_message}
331 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
334 test "is not empty but activity doesn't have a matching host" do
335 clear_config([:mrf_simple, :accept], ["non.matching.remote"])
337 local_message = build_local_message()
338 remote_message = build_remote_message()
340 assert SimplePolicy.filter(local_message) == {:ok, local_message}
341 assert {:reject, _} = SimplePolicy.filter(remote_message)
344 test "activity has a matching host" do
345 clear_config([:mrf_simple, :accept], ["remote.instance"])
347 local_message = build_local_message()
348 remote_message = build_remote_message()
350 assert SimplePolicy.filter(local_message) == {:ok, local_message}
351 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
354 test "activity matches with wildcard domain" do
355 clear_config([:mrf_simple, :accept], ["*.remote.instance"])
357 local_message = build_local_message()
358 remote_message = build_remote_message()
360 assert SimplePolicy.filter(local_message) == {:ok, local_message}
361 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
364 test "actor has a matching host" do
365 clear_config([:mrf_simple, :accept], ["remote.instance"])
367 remote_user = build_remote_user()
369 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
373 describe "when :avatar_removal" do
375 clear_config([:mrf_simple, :avatar_removal], [])
377 remote_user = build_remote_user()
379 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
382 test "is not empty but it doesn't have a matching host" do
383 clear_config([:mrf_simple, :avatar_removal], ["non.matching.remote"])
385 remote_user = build_remote_user()
387 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
390 test "has a matching host" do
391 clear_config([:mrf_simple, :avatar_removal], ["remote.instance"])
393 remote_user = build_remote_user()
394 {:ok, filtered} = SimplePolicy.filter(remote_user)
396 refute filtered["icon"]
399 test "match with wildcard domain" do
400 clear_config([:mrf_simple, :avatar_removal], ["*.remote.instance"])
402 remote_user = build_remote_user()
403 {:ok, filtered} = SimplePolicy.filter(remote_user)
405 refute filtered["icon"]
409 describe "when :banner_removal" do
411 clear_config([:mrf_simple, :banner_removal], [])
413 remote_user = build_remote_user()
415 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
418 test "is not empty but it doesn't have a matching host" do
419 clear_config([:mrf_simple, :banner_removal], ["non.matching.remote"])
421 remote_user = build_remote_user()
423 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
426 test "has a matching host" do
427 clear_config([:mrf_simple, :banner_removal], ["remote.instance"])
429 remote_user = build_remote_user()
430 {:ok, filtered} = SimplePolicy.filter(remote_user)
432 refute filtered["image"]
435 test "match with wildcard domain" do
436 clear_config([:mrf_simple, :banner_removal], ["*.remote.instance"])
438 remote_user = build_remote_user()
439 {:ok, filtered} = SimplePolicy.filter(remote_user)
441 refute filtered["image"]
445 describe "when :reject_deletes is empty" do
446 setup do: clear_config([:mrf_simple, :reject_deletes], [])
448 test "it accepts deletions even from rejected servers" do
449 clear_config([:mrf_simple, :reject], ["remote.instance"])
451 deletion_message = build_remote_deletion_message()
453 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
456 test "it accepts deletions even from non-whitelisted servers" do
457 clear_config([:mrf_simple, :accept], ["non.matching.remote"])
459 deletion_message = build_remote_deletion_message()
461 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
465 describe "when :reject_deletes is not empty but it doesn't have a matching host" do
466 setup do: clear_config([:mrf_simple, :reject_deletes], ["non.matching.remote"])
468 test "it accepts deletions even from rejected servers" do
469 clear_config([:mrf_simple, :reject], ["remote.instance"])
471 deletion_message = build_remote_deletion_message()
473 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
476 test "it accepts deletions even from non-whitelisted servers" do
477 clear_config([:mrf_simple, :accept], ["non.matching.remote"])
479 deletion_message = build_remote_deletion_message()
481 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
485 describe "when :reject_deletes has a matching host" do
486 setup do: clear_config([:mrf_simple, :reject_deletes], ["remote.instance"])
488 test "it rejects the deletion" do
489 deletion_message = build_remote_deletion_message()
491 assert {:reject, _} = SimplePolicy.filter(deletion_message)
495 describe "when :reject_deletes match with wildcard domain" do
496 setup do: clear_config([:mrf_simple, :reject_deletes], ["*.remote.instance"])
498 test "it rejects the deletion" do
499 deletion_message = build_remote_deletion_message()
501 assert {:reject, _} = SimplePolicy.filter(deletion_message)
505 defp build_local_message do
507 "actor" => "#{Pleroma.Web.base_url()}/users/alice",
513 defp build_remote_message do
514 %{"actor" => "https://remote.instance/users/bob"}
517 defp build_remote_user do
519 "id" => "https://remote.instance/users/bob",
521 "url" => "http://example.com/image.jpg",
525 "url" => "http://example.com/image.jpg",
532 defp build_remote_deletion_message do
535 "actor" => "https://remote.instance/users/bob"