1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 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"]
295 |> Map.fetch!("actor")
299 Config.put([:mrf_simple, :followers_only], [actor_domain])
301 assert {:ok, new_activity} = SimplePolicy.filter(activity)
302 assert actor.follower_address in new_activity["to"]
303 assert following_user.ap_id in new_activity["to"]
304 refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["to"]
305 refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["cc"]
306 refute non_following_user.ap_id in new_activity["to"]
307 refute non_following_user.ap_id in new_activity["cc"]
311 describe "when :accept" do
313 Config.put([:mrf_simple, :accept], [])
315 local_message = build_local_message()
316 remote_message = build_remote_message()
318 assert SimplePolicy.filter(local_message) == {:ok, local_message}
319 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
322 test "is not empty but activity doesn't have a matching host" do
323 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
325 local_message = build_local_message()
326 remote_message = build_remote_message()
328 assert SimplePolicy.filter(local_message) == {:ok, local_message}
329 assert {:reject, _} = SimplePolicy.filter(remote_message)
332 test "activity has a matching host" do
333 Config.put([:mrf_simple, :accept], ["remote.instance"])
335 local_message = build_local_message()
336 remote_message = build_remote_message()
338 assert SimplePolicy.filter(local_message) == {:ok, local_message}
339 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
342 test "activity matches with wildcard domain" do
343 Config.put([:mrf_simple, :accept], ["*.remote.instance"])
345 local_message = build_local_message()
346 remote_message = build_remote_message()
348 assert SimplePolicy.filter(local_message) == {:ok, local_message}
349 assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
352 test "actor has a matching host" do
353 Config.put([:mrf_simple, :accept], ["remote.instance"])
355 remote_user = build_remote_user()
357 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
361 describe "when :avatar_removal" do
363 Config.put([:mrf_simple, :avatar_removal], [])
365 remote_user = build_remote_user()
367 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
370 test "is not empty but it doesn't have a matching host" do
371 Config.put([:mrf_simple, :avatar_removal], ["non.matching.remote"])
373 remote_user = build_remote_user()
375 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
378 test "has a matching host" do
379 Config.put([:mrf_simple, :avatar_removal], ["remote.instance"])
381 remote_user = build_remote_user()
382 {:ok, filtered} = SimplePolicy.filter(remote_user)
384 refute filtered["icon"]
387 test "match with wildcard domain" do
388 Config.put([:mrf_simple, :avatar_removal], ["*.remote.instance"])
390 remote_user = build_remote_user()
391 {:ok, filtered} = SimplePolicy.filter(remote_user)
393 refute filtered["icon"]
397 describe "when :banner_removal" do
399 Config.put([:mrf_simple, :banner_removal], [])
401 remote_user = build_remote_user()
403 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
406 test "is not empty but it doesn't have a matching host" do
407 Config.put([:mrf_simple, :banner_removal], ["non.matching.remote"])
409 remote_user = build_remote_user()
411 assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
414 test "has a matching host" do
415 Config.put([:mrf_simple, :banner_removal], ["remote.instance"])
417 remote_user = build_remote_user()
418 {:ok, filtered} = SimplePolicy.filter(remote_user)
420 refute filtered["image"]
423 test "match with wildcard domain" do
424 Config.put([:mrf_simple, :banner_removal], ["*.remote.instance"])
426 remote_user = build_remote_user()
427 {:ok, filtered} = SimplePolicy.filter(remote_user)
429 refute filtered["image"]
433 describe "when :reject_deletes is empty" do
434 setup do: Config.put([:mrf_simple, :reject_deletes], [])
436 test "it accepts deletions even from rejected servers" do
437 Config.put([:mrf_simple, :reject], ["remote.instance"])
439 deletion_message = build_remote_deletion_message()
441 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
444 test "it accepts deletions even from non-whitelisted servers" do
445 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
447 deletion_message = build_remote_deletion_message()
449 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
453 describe "when :reject_deletes is not empty but it doesn't have a matching host" do
454 setup do: Config.put([:mrf_simple, :reject_deletes], ["non.matching.remote"])
456 test "it accepts deletions even from rejected servers" do
457 Config.put([:mrf_simple, :reject], ["remote.instance"])
459 deletion_message = build_remote_deletion_message()
461 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
464 test "it accepts deletions even from non-whitelisted servers" do
465 Config.put([:mrf_simple, :accept], ["non.matching.remote"])
467 deletion_message = build_remote_deletion_message()
469 assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
473 describe "when :reject_deletes has a matching host" do
474 setup do: Config.put([:mrf_simple, :reject_deletes], ["remote.instance"])
476 test "it rejects the deletion" do
477 deletion_message = build_remote_deletion_message()
479 assert {:reject, _} = SimplePolicy.filter(deletion_message)
483 describe "when :reject_deletes match with wildcard domain" do
484 setup do: Config.put([:mrf_simple, :reject_deletes], ["*.remote.instance"])
486 test "it rejects the deletion" do
487 deletion_message = build_remote_deletion_message()
489 assert {:reject, _} = SimplePolicy.filter(deletion_message)
493 defp build_local_message do
495 "actor" => "#{Pleroma.Web.base_url()}/users/alice",
501 defp build_remote_message do
502 %{"actor" => "https://remote.instance/users/bob"}
505 defp build_remote_user do
507 "id" => "https://remote.instance/users/bob",
509 "url" => "http://example.com/image.jpg",
513 "url" => "http://example.com/image.jpg",
520 defp build_remote_deletion_message do
523 "actor" => "https://remote.instance/users/bob"