Browse Source

insreasing test coverage for StealEmojiPolicy

groups
Alexander Strizhakov 3 years ago
parent
commit
7bfb041658
No known key found for this signature in database GPG Key ID: 22896A53AEF1381
2 changed files with 103 additions and 64 deletions
  1. +33
    -31
      lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
  2. +70
    -33
      test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs

+ 33
- 31
lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex View 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?


+ 70
- 33
test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs View 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

Loading…
Cancel
Save