logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

simple_policy_test.exs (16862B)


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