insreasing test coverage for StealEmojiPolicy
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Fri, 25 Dec 2020 08:30:36 +0000 (11:30 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Sun, 27 Dec 2020 18:53:30 +0000 (21:53 +0300)
lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs

index eabee654209d53f052fc7ec85c8144c3f64e63d7..0311ca43393a51647d37b5a4f626094f17e77a53 100644 (file)
@@ -10,52 +10,53 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
   @moduledoc "Detect new emojis by their shortcode and steals them"
   @behaviour Pleroma.Web.ActivityPub.MRF
 
-  defp remote_host?(host), do: host != Config.get([Pleroma.Web.Endpoint, :url, :host])
-
   defp accept_host?(host), do: host in Config.get([:mrf_steal_emoji, :hosts], [])
 
   defp steal_emoji({shortcode, url}, emoji_dir_path) do
     url = Pleroma.Web.MediaProxy.url(url)
-    {:ok, response} = Pleroma.HTTP.get(url)
-    size_limit = Config.get([:mrf_steal_emoji, :size_limit], 50_000)
 
-    if byte_size(response.body) <= size_limit do
-      extension =
-        url
-        |> URI.parse()
-        |> Map.get(:path)
-        |> Path.basename()
-        |> Path.extname()
+    with {:ok, %{status: status} = response} when status in 200..299 <- Pleroma.HTTP.get(url) do
+      size_limit = Config.get([:mrf_steal_emoji, :size_limit], 50_000)
+
+      if byte_size(response.body) <= size_limit do
+        extension =
+          url
+          |> URI.parse()
+          |> Map.get(:path)
+          |> Path.basename()
+          |> Path.extname()
+
+        file_path = Path.join(emoji_dir_path, shortcode <> (extension || ".png"))
 
-      file_path = Path.join([emoji_dir_path, shortcode <> (extension || ".png")])
+        case File.write(file_path, response.body) do
+          :ok ->
+            shortcode
 
-      with :ok <- File.write(file_path, response.body) do
-        shortcode
+          e ->
+            Logger.warn("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}")
+            nil
+        end
       else
-        e ->
-          Logger.warn("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}")
-          nil
+        Logger.debug(
+          "MRF.StealEmojiPolicy: :#{shortcode}: at #{url} (#{byte_size(response.body)} B) over size limit (#{
+            size_limit
+          } B)"
+        )
+
+        nil
       end
     else
-      Logger.debug(
-        "MRF.StealEmojiPolicy: :#{shortcode}: at #{url} (#{byte_size(response.body)} B) over size limit (#{
-          size_limit
-        } B)"
-      )
-
-      nil
+      e ->
+        Logger.warn("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
+        nil
     end
-  rescue
-    e ->
-      Logger.warn("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
-      nil
   end
 
   @impl true
   def filter(%{"object" => %{"emoji" => foreign_emojis, "actor" => actor}} = message) do
     host = URI.parse(actor).host
 
-    if remote_host?(host) and accept_host?(host) do
+    if host != Pleroma.Web.Endpoint.host() and accept_host?(host) do
       installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
 
       emoji_dir_path =
@@ -70,10 +71,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
 
       new_emojis =
         foreign_emojis
-        |> Enum.filter(fn {shortcode, _url} -> shortcode not in installed_emoji end)
+        |> Enum.reject(fn {shortcode, _url} -> shortcode in installed_emoji end)
         |> Enum.filter(fn {shortcode, _url} ->
           reject_emoji? =
-            Config.get([:mrf_steal_emoji, :rejected_shortcodes], [])
+            [:mrf_steal_emoji, :rejected_shortcodes]
+            |> Config.get([])
             |> Enum.find(false, fn regex -> String.match?(shortcode, regex) end)
 
           !reject_emoji?
index 3f8222736ec591dbcc449aedcedc46280b27b1b1..7665d00d0c2e1dadfdf9c6d75a248b30ad1b3520 100644 (file)
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do
   use Pleroma.DataCase
 
   alias Pleroma.Config
+  alias Pleroma.Emoji
   alias Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy
 
   setup_all do
@@ -14,22 +15,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do
   end
 
   setup do
-    emoji_path = Path.join(Config.get([:instance, :static_dir]), "emoji/stolen")
-    File.rm_rf!(emoji_path)
-    File.mkdir!(emoji_path)
+    emoji_path = [:instance, :static_dir] |> Config.get() |> Path.join("emoji/stolen")
 
-    Pleroma.Emoji.reload()
-
-    on_exit(fn ->
-      File.rm_rf!(emoji_path)
-    end)
-
-    :ok
-  end
-
-  test "does nothing by default" do
-    installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
-    refute "firedfox" in installed_emoji
+    Emoji.reload()
 
     message = %{
       "type" => "Create",
@@ -39,30 +27,79 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do
       }
     }
 
-    assert {:ok, message} == StealEmojiPolicy.filter(message)
+    on_exit(fn ->
+      File.rm_rf!(emoji_path)
+    end)
 
-    installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
-    refute "firedfox" in installed_emoji
+    [message: message, path: emoji_path]
   end
 
-  test "Steals emoji on unknown shortcode from allowed remote host" do
-    installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
-    refute "firedfox" in installed_emoji
+  test "does nothing by default", %{message: message} do
+    refute "firedfox" in installed()
 
-    message = %{
-      "type" => "Create",
-      "object" => %{
-        "emoji" => [{"firedfox", "https://example.org/emoji/firedfox.png"}],
-        "actor" => "https://example.org/users/admin"
-      }
-    }
+    assert {:ok, _message} = StealEmojiPolicy.filter(message)
+
+    refute "firedfox" in installed()
+  end
 
-    clear_config([:mrf_steal_emoji, :hosts], ["example.org"])
-    clear_config([:mrf_steal_emoji, :size_limit], 284_468)
+  test "Steals emoji on unknown shortcode from allowed remote host", %{
+    message: message,
+    path: path
+  } do
+    refute "firedfox" in installed()
+    refute File.exists?(path)
 
-    assert {:ok, message} == StealEmojiPolicy.filter(message)
+    clear_config(:mrf_steal_emoji, hosts: ["example.org"], size_limit: 284_468)
 
-    installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
-    assert "firedfox" in installed_emoji
+    assert {:ok, _message} = StealEmojiPolicy.filter(message)
+
+    assert "firedfox" in installed()
+    assert File.exists?(path)
+
+    assert path
+           |> Path.join("firedfox.png")
+           |> File.exists?()
+  end
+
+  test "reject shortcode", %{message: message} do
+    refute "firedfox" in installed()
+
+    clear_config(:mrf_steal_emoji,
+      hosts: ["example.org"],
+      size_limit: 284_468,
+      rejected_shortcodes: [~r/firedfox/]
+    )
+
+    assert {:ok, _message} = StealEmojiPolicy.filter(message)
+
+    refute "firedfox" in installed()
+  end
+
+  test "reject if size is above the limit", %{message: message} do
+    refute "firedfox" in installed()
+
+    clear_config(:mrf_steal_emoji, hosts: ["example.org"], size_limit: 50_000)
+
+    assert {:ok, _message} = StealEmojiPolicy.filter(message)
+
+    refute "firedfox" in installed()
+  end
+
+  test "reject if host returns error", %{message: message} do
+    refute "firedfox" in installed()
+
+    Tesla.Mock.mock(fn %{method: :get, url: "https://example.org/emoji/firedfox.png"} ->
+      {:ok, %Tesla.Env{status: 404, body: "Not found"}}
+    end)
+
+    clear_config(:mrf_steal_emoji, hosts: ["example.org"], size_limit: 284_468)
+
+    ExUnit.CaptureLog.capture_log(fn ->
+      assert {:ok, _message} = StealEmojiPolicy.filter(message)
+    end) =~ "MRF.StealEmojiPolicy: Failed to fetch https://example.org/emoji/firedfox.png"
+
+    refute "firedfox" in installed()
   end
+
+  defp installed, do: Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
 end