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) ==
78 {:ok, put_in(media_message, ["object", "sensitive"], true)}
80 assert SimplePolicy.filter(local_message) == {:ok, local_message}
83 test "match with wildcard domain" do
84 clear_config([:mrf_simple, :media_nsfw], ["*.remote.instance"])
85 media_message = build_media_message()
86 local_message = build_local_message()
88 assert SimplePolicy.filter(media_message) ==
89 {:ok, put_in(media_message, ["object", "sensitive"], true)}
91 assert SimplePolicy.filter(local_message) == {:ok, local_message}
95 defp build_media_message do
97 "actor" => "https://remote.instance/users/bob",
100 "attachment" => [%{}],
107 describe "when :report_removal" do
109 clear_config([:mrf_simple, :report_removal], [])
110 report_message = build_report_message()
111 local_message = build_local_message()
113 assert SimplePolicy.filter(report_message) == {:ok, report_message}
114 assert SimplePolicy.filter(local_message) == {:ok, local_message}
117 test "has a matching host" do
118 clear_config([:mrf_simple, :report_removal], ["remote.instance"])
119 report_message = build_report_message()
120 local_message = build_local_message()
122 assert {:reject, _} = SimplePolicy.filter(report_message)
123 assert SimplePolicy.filter(local_message) == {:ok, local_message}
126 test "match with wildcard domain" do
127 clear_config([:mrf_simple, :report_removal], ["*.remote.instance"])
128 report_message = build_report_message()
129 local_message = build_local_message()
131 assert {:reject, _} = SimplePolicy.filter(report_message)
132 assert SimplePolicy.filter(local_message) == {:ok, local_message}
136 defp build_report_message do
138 "actor" => "https://remote.instance/users/bob",
143 describe "when :federated_timeline_removal" do
145 clear_config([:mrf_simple, :federated_timeline_removal], [])
146 {_, ftl_message} = build_ftl_actor_and_message()
147 local_message = build_local_message()
149 assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
150 assert SimplePolicy.filter(local_message) == {:ok, local_message}
153 test "has a matching host" do
154 {actor, ftl_message} = build_ftl_actor_and_message()
156 ftl_message_actor_host =
158 |> Map.fetch!("actor")
162 clear_config([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
163 local_message = build_local_message()
165 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
166 assert actor.follower_address in ftl_message["to"]
167 refute actor.follower_address in ftl_message["cc"]
168 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
169 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
171 assert SimplePolicy.filter(local_message) == {:ok, local_message}
174 test "match with wildcard domain" do
175 {actor, ftl_message} = build_ftl_actor_and_message()
177 ftl_message_actor_host =
179 |> Map.fetch!("actor")
183 clear_config([:mrf_simple, :federated_timeline_removal], ["*." <> ftl_message_actor_host])
184 local_message = build_local_message()
186 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
187 assert actor.follower_address in ftl_message["to"]
188 refute actor.follower_address in ftl_message["cc"]
189 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
190 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
192 assert SimplePolicy.filter(local_message) == {:ok, local_message}
195 test "has a matching host but only as:Public in to" do
196 {_actor, ftl_message} = build_ftl_actor_and_message()
198 ftl_message_actor_host =
200 |> Map.fetch!("actor")
204 ftl_message = Map.put(ftl_message, "cc", [])
206 clear_config([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
208 assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
209 refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
210 assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
214 defp build_ftl_actor_and_message do
215 actor = insert(:user)
219 "actor" => actor.ap_id,
220 "to" => ["https://www.w3.org/ns/activitystreams#Public", "http://foo.bar/baz"],
221 "cc" => [actor.follower_address, "http://foo.bar/qux"]
225 describe "when :reject" do
227 clear_config([:mrf_simple, :reject], [])
229 remote_message = build_remote_message()
231 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
234 test "activity has a matching host" do
235 clear_config([:mrf_simple, :reject], ["remote.instance"])
237 remote_message = build_remote_message()
239 assert {:reject, _} = SimplePolicy.filter(remote_message)
242 test "activity matches with wildcard domain" do
243 clear_config([:mrf_simple, :reject], ["*.remote.instance"])
245 remote_message = build_remote_message()
247 assert {:reject, _} = SimplePolicy.filter(remote_message)
250 test "actor has a matching host" do
251 clear_config([:mrf_simple, :reject], ["remote.instance"])
253 remote_user = build_remote_user()
255 assert {:reject, _} = SimplePolicy.filter(remote_user)
259 describe "when :followers_only" do
261 clear_config([:mrf_simple, :followers_only], [])
262 {_, ftl_message} = build_ftl_actor_and_message()
263 local_message = build_local_message()
265 assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
266 assert SimplePolicy.filter(local_message) == {:ok, local_message}
269 test "has a matching host" do
270 actor = insert(:user)
271 following_user = insert(:user)
272 non_following_user = insert(:user)
274 {:ok, _, _, _} = CommonAPI.follow(following_user, actor)
277 "actor" => actor.ap_id,
279 "https://www.w3.org/ns/activitystreams#Public",
280 following_user.ap_id,
281 non_following_user.ap_id
283 "cc" => [actor.follower_address, "http://foo.bar/qux"]
287 "actor" => actor.ap_id,
289 following_user.ap_id,
290 non_following_user.ap_id
297 |> Map.fetch!("actor")
301 clear_config([:mrf_simple, :followers_only], [actor_domain])
303 assert {:ok, new_activity} = SimplePolicy.filter(activity)
304 assert actor.follower_address in new_activity["cc"]
305 assert following_user.ap_id in new_activity["to"]
306 refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["to"]
307 refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["cc"]
308 refute non_following_user.ap_id in new_activity["to"]
309 refute non_following_user.ap_id in new_activity["cc"]
311 assert {:ok, new_dm_activity} = SimplePolicy.filter(dm_activity)
312 assert new_dm_activity["to"] == [following_user.ap_id]
313 assert new_dm_activity["cc"] == []
317 describe "when :accept" do
319 clear_config([:mrf_simple, :accept], [])
321 local_message = build_local_message()
322 remote_message = build_remote_message()
324 assert SimplePolicy.filter(local_message) == {:ok, local_message}
325 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
328 test "is not empty but activity doesn't have a matching host" do
329 clear_config([:mrf_simple, :accept], ["non.matching.remote"])
331 local_message = build_local_message()
332 remote_message = build_remote_message()
334 assert SimplePolicy.filter(local_message) == {:ok, local_message}
335 assert {:reject, _} = SimplePolicy.filter(remote_message)
338 test "activity has a matching host" do
339 clear_config([:mrf_simple, :accept], ["remote.instance"])
341 local_message = build_local_message()
342 remote_message = build_remote_message()
344 assert SimplePolicy.filter(local_message) == {:ok, local_message}
345 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
348 test "activity matches with wildcard domain" do
349 clear_config([:mrf_simple, :accept], ["*.remote.instance"])
351 local_message = build_local_message()
352 remote_message = build_remote_message()
354 assert SimplePolicy.filter(local_message) == {:ok, local_message}
355 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
358 test "actor has a matching host" do
359 clear_config([:mrf_simple, :accept], ["remote.instance"])
361 remote_user = build_remote_user()
363 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
367 describe "when :avatar_removal" do
369 clear_config([:mrf_simple, :avatar_removal], [])
371 remote_user = build_remote_user()
373 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
376 test "is not empty but it doesn't have a matching host" do
377 clear_config([:mrf_simple, :avatar_removal], ["non.matching.remote"])
379 remote_user = build_remote_user()
381 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
384 test "has a matching host" do
385 clear_config([:mrf_simple, :avatar_removal], ["remote.instance"])
387 remote_user = build_remote_user()
388 {:ok, filtered} = SimplePolicy.filter(remote_user)
390 refute filtered["icon"]
393 test "match with wildcard domain" do
394 clear_config([:mrf_simple, :avatar_removal], ["*.remote.instance"])
396 remote_user = build_remote_user()
397 {:ok, filtered} = SimplePolicy.filter(remote_user)
399 refute filtered["icon"]
403 describe "when :banner_removal" do
405 clear_config([:mrf_simple, :banner_removal], [])
407 remote_user = build_remote_user()
409 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
412 test "is not empty but it doesn't have a matching host" do
413 clear_config([:mrf_simple, :banner_removal], ["non.matching.remote"])
415 remote_user = build_remote_user()
417 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
420 test "has a matching host" do
421 clear_config([:mrf_simple, :banner_removal], ["remote.instance"])
423 remote_user = build_remote_user()
424 {:ok, filtered} = SimplePolicy.filter(remote_user)
426 refute filtered["image"]
429 test "match with wildcard domain" do
430 clear_config([:mrf_simple, :banner_removal], ["*.remote.instance"])
432 remote_user = build_remote_user()
433 {:ok, filtered} = SimplePolicy.filter(remote_user)
435 refute filtered["image"]
439 describe "when :reject_deletes is empty" do
440 setup do: clear_config([:mrf_simple, :reject_deletes], [])
442 test "it accepts deletions even from rejected servers" do
443 clear_config([:mrf_simple, :reject], ["remote.instance"])
445 deletion_message = build_remote_deletion_message()
447 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
450 test "it accepts deletions even from non-whitelisted servers" do
451 clear_config([:mrf_simple, :accept], ["non.matching.remote"])
453 deletion_message = build_remote_deletion_message()
455 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
459 describe "when :reject_deletes is not empty but it doesn't have a matching host" do
460 setup do: clear_config([:mrf_simple, :reject_deletes], ["non.matching.remote"])
462 test "it accepts deletions even from rejected servers" do
463 clear_config([:mrf_simple, :reject], ["remote.instance"])
465 deletion_message = build_remote_deletion_message()
467 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
470 test "it accepts deletions even from non-whitelisted servers" do
471 clear_config([:mrf_simple, :accept], ["non.matching.remote"])
473 deletion_message = build_remote_deletion_message()
475 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
479 describe "when :reject_deletes has a matching host" do
480 setup do: clear_config([:mrf_simple, :reject_deletes], ["remote.instance"])
482 test "it rejects the deletion" do
483 deletion_message = build_remote_deletion_message()
485 assert {:reject, _} = SimplePolicy.filter(deletion_message)
489 describe "when :reject_deletes match with wildcard domain" do
490 setup do: clear_config([:mrf_simple, :reject_deletes], ["*.remote.instance"])
492 test "it rejects the deletion" do
493 deletion_message = build_remote_deletion_message()
495 assert {:reject, _} = SimplePolicy.filter(deletion_message)
499 defp build_local_message do
501 "actor" => "#{Pleroma.Web.base_url()}/users/alice",
507 defp build_remote_message do
508 %{"actor" => "https://remote.instance/users/bob"}
511 defp build_remote_user do
513 "id" => "https://remote.instance/users/bob",
515 "url" => "http://example.com/image.jpg",
519 "url" => "http://example.com/image.jpg",
526 defp build_remote_deletion_message do
529 "actor" => "https://remote.instance/users/bob"