Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

557 řádky
17KB

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