logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/

nsfw_api_policy_test.exs (8705B)


  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.NsfwApiPolicyTest do
  5. use Pleroma.DataCase
  6. import ExUnit.CaptureLog
  7. import Pleroma.Factory
  8. alias Pleroma.Constants
  9. alias Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy
  10. require Pleroma.Constants
  11. @policy :mrf_nsfw_api
  12. @sfw_url "https://kittens.co/kitty.gif"
  13. @nsfw_url "https://b00bies.com/nsfw.jpg"
  14. @timeout_url "http://time.out/i.jpg"
  15. setup_all do
  16. clear_config(@policy,
  17. url: "http://127.0.0.1:5000/",
  18. threshold: 0.7,
  19. mark_sensitive: true,
  20. unlist: false,
  21. reject: false
  22. )
  23. end
  24. setup do
  25. Tesla.Mock.mock(fn
  26. # NSFW URL
  27. %{method: :get, url: "http://127.0.0.1:5000/?url=#{@nsfw_url}"} ->
  28. %Tesla.Env{status: 200, body: ~s({"score":0.99772077798843384,"url":"#{@nsfw_url}"})}
  29. # SFW URL
  30. %{method: :get, url: "http://127.0.0.1:5000/?url=#{@sfw_url}"} ->
  31. %Tesla.Env{status: 200, body: ~s({"score":0.00011714912398019806,"url":"#{@sfw_url}"})}
  32. # Timeout URL
  33. %{method: :get, url: "http://127.0.0.1:5000/?url=#{@timeout_url}"} ->
  34. {:error, :timeout}
  35. # Fallback URL
  36. %{method: :get, url: "http://127.0.0.1:5000/?url=" <> url} ->
  37. body =
  38. ~s({"error_code":500,"error_reason":"[Errno -2] Name or service not known","url":"#{url}"})
  39. %Tesla.Env{status: 500, body: body}
  40. end)
  41. :ok
  42. end
  43. describe "build_request_url/1" do
  44. test "it works" do
  45. expected = "http://127.0.0.1:5000/?url=https://b00bies.com/nsfw.jpg"
  46. assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
  47. end
  48. test "it adds a trailing slash" do
  49. clear_config([@policy, :url], "http://localhost:5000")
  50. expected = "http://localhost:5000/?url=https://b00bies.com/nsfw.jpg"
  51. assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
  52. end
  53. test "it adds a trailing slash preserving the path" do
  54. clear_config([@policy, :url], "http://localhost:5000/nsfw_api")
  55. expected = "http://localhost:5000/nsfw_api/?url=https://b00bies.com/nsfw.jpg"
  56. assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
  57. end
  58. end
  59. describe "parse_url/1" do
  60. test "returns decoded JSON from the API server" do
  61. expected = %{"score" => 0.99772077798843384, "url" => @nsfw_url}
  62. assert NsfwApiPolicy.parse_url(@nsfw_url) == {:ok, expected}
  63. end
  64. test "warns when the API server fails" do
  65. expected = "[NsfwApiPolicy]: The API server failed. Skipping."
  66. assert capture_log(fn -> NsfwApiPolicy.parse_url(@timeout_url) end) =~ expected
  67. end
  68. test "returns {:error, _} tuple when the API server fails" do
  69. capture_log(fn ->
  70. assert {:error, _} = NsfwApiPolicy.parse_url(@timeout_url)
  71. end)
  72. end
  73. end
  74. describe "check_url_nsfw/1" do
  75. test "returns {:nsfw, _} tuple" do
  76. expected = {:nsfw, %{url: @nsfw_url, score: 0.99772077798843384, threshold: 0.7}}
  77. assert NsfwApiPolicy.check_url_nsfw(@nsfw_url) == expected
  78. end
  79. test "returns {:sfw, _} tuple" do
  80. expected = {:sfw, %{url: @sfw_url, score: 0.00011714912398019806, threshold: 0.7}}
  81. assert NsfwApiPolicy.check_url_nsfw(@sfw_url) == expected
  82. end
  83. test "returns {:sfw, _} on failure" do
  84. expected = {:sfw, %{url: @timeout_url, score: nil, threshold: 0.7}}
  85. capture_log(fn ->
  86. assert NsfwApiPolicy.check_url_nsfw(@timeout_url) == expected
  87. end)
  88. end
  89. test "works with map URL" do
  90. expected = {:nsfw, %{url: @nsfw_url, score: 0.99772077798843384, threshold: 0.7}}
  91. assert NsfwApiPolicy.check_url_nsfw(%{"href" => @nsfw_url}) == expected
  92. end
  93. end
  94. describe "check_attachment_nsfw/1" do
  95. test "returns {:nsfw, _} if any items are NSFW" do
  96. attachment = %{"url" => [%{"href" => @nsfw_url}, @nsfw_url, @sfw_url]}
  97. assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:nsfw, attachment}
  98. end
  99. test "returns {:sfw, _} if all items are SFW" do
  100. attachment = %{"url" => [%{"href" => @sfw_url}, @sfw_url, @sfw_url]}
  101. assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:sfw, attachment}
  102. end
  103. test "works with binary URL" do
  104. attachment = %{"url" => @nsfw_url}
  105. assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:nsfw, attachment}
  106. end
  107. end
  108. describe "check_object_nsfw/1" do
  109. test "returns {:nsfw, _} if any items are NSFW" do
  110. object = %{"attachment" => [%{"url" => [%{"href" => @nsfw_url}, @sfw_url]}]}
  111. assert NsfwApiPolicy.check_object_nsfw(object) == {:nsfw, object}
  112. end
  113. test "returns {:sfw, _} if all items are SFW" do
  114. object = %{"attachment" => [%{"url" => [%{"href" => @sfw_url}, @sfw_url]}]}
  115. assert NsfwApiPolicy.check_object_nsfw(object) == {:sfw, object}
  116. end
  117. test "works with embedded object" do
  118. object = %{"object" => %{"attachment" => [%{"url" => [%{"href" => @nsfw_url}, @sfw_url]}]}}
  119. assert NsfwApiPolicy.check_object_nsfw(object) == {:nsfw, object}
  120. end
  121. end
  122. describe "unlist/1" do
  123. test "unlist addressing" do
  124. user = insert(:user)
  125. object = %{
  126. "to" => [Constants.as_public()],
  127. "cc" => [user.follower_address, "https://hello.world/users/alex"],
  128. "actor" => user.ap_id
  129. }
  130. expected = %{
  131. "to" => [user.follower_address],
  132. "cc" => [Constants.as_public(), "https://hello.world/users/alex"],
  133. "actor" => user.ap_id
  134. }
  135. assert NsfwApiPolicy.unlist(object) == expected
  136. end
  137. test "raise if user isn't found" do
  138. object = %{
  139. "to" => [Constants.as_public()],
  140. "cc" => [],
  141. "actor" => "https://hello.world/users/alex"
  142. }
  143. assert_raise(RuntimeError, fn ->
  144. NsfwApiPolicy.unlist(object)
  145. end)
  146. end
  147. end
  148. describe "mark_sensitive/1" do
  149. test "adds nsfw tag and marks sensitive" do
  150. object = %{"tag" => ["yolo"]}
  151. expected = %{"tag" => ["yolo", "nsfw"], "sensitive" => true}
  152. assert NsfwApiPolicy.mark_sensitive(object) == expected
  153. end
  154. test "works with embedded object" do
  155. object = %{"object" => %{"tag" => ["yolo"]}}
  156. expected = %{"object" => %{"tag" => ["yolo", "nsfw"], "sensitive" => true}}
  157. assert NsfwApiPolicy.mark_sensitive(object) == expected
  158. end
  159. end
  160. describe "filter/1" do
  161. setup do
  162. user = insert(:user)
  163. nsfw_object = %{
  164. "to" => [Constants.as_public()],
  165. "cc" => [user.follower_address],
  166. "actor" => user.ap_id,
  167. "attachment" => [%{"url" => @nsfw_url}]
  168. }
  169. sfw_object = %{
  170. "to" => [Constants.as_public()],
  171. "cc" => [user.follower_address],
  172. "actor" => user.ap_id,
  173. "attachment" => [%{"url" => @sfw_url}]
  174. }
  175. %{user: user, nsfw_object: nsfw_object, sfw_object: sfw_object}
  176. end
  177. test "passes SFW object through", %{sfw_object: object} do
  178. {:ok, _} = NsfwApiPolicy.filter(object)
  179. end
  180. test "passes NSFW object through when actions are disabled", %{nsfw_object: object} do
  181. clear_config([@policy, :mark_sensitive], false)
  182. clear_config([@policy, :unlist], false)
  183. clear_config([@policy, :reject], false)
  184. {:ok, _} = NsfwApiPolicy.filter(object)
  185. end
  186. test "passes NSFW object through when :threshold is 1", %{nsfw_object: object} do
  187. clear_config([@policy, :reject], true)
  188. clear_config([@policy, :threshold], 1)
  189. {:ok, _} = NsfwApiPolicy.filter(object)
  190. end
  191. test "rejects SFW object through when :threshold is 0", %{sfw_object: object} do
  192. clear_config([@policy, :reject], true)
  193. clear_config([@policy, :threshold], 0)
  194. {:reject, _} = NsfwApiPolicy.filter(object)
  195. end
  196. test "rejects NSFW when :reject is enabled", %{nsfw_object: object} do
  197. clear_config([@policy, :reject], true)
  198. {:reject, _} = NsfwApiPolicy.filter(object)
  199. end
  200. test "passes NSFW through when :reject is disabled", %{nsfw_object: object} do
  201. clear_config([@policy, :reject], false)
  202. {:ok, _} = NsfwApiPolicy.filter(object)
  203. end
  204. test "unlists NSFW when :unlist is enabled", %{user: user, nsfw_object: object} do
  205. clear_config([@policy, :unlist], true)
  206. {:ok, object} = NsfwApiPolicy.filter(object)
  207. assert object["to"] == [user.follower_address]
  208. end
  209. test "passes NSFW through when :unlist is disabled", %{nsfw_object: object} do
  210. clear_config([@policy, :unlist], false)
  211. {:ok, object} = NsfwApiPolicy.filter(object)
  212. assert object["to"] == [Constants.as_public()]
  213. end
  214. end
  215. end