mediaproxy: fix empty url & add some tests
authorhref <href@random.sh>
Tue, 20 Nov 2018 16:46:54 +0000 (17:46 +0100)
committerhref <href@random.sh>
Tue, 20 Nov 2018 16:50:03 +0000 (17:50 +0100)
lib/pleroma/web/media_proxy/media_proxy.ex
test/media_proxy_test.exs [new file with mode: 0644]

index 93c36b4ed3668f15634bed6c49402772c436a418..0fc0a07b269d3bb6af0baf5897e73ffc0bf8c459 100644 (file)
@@ -3,6 +3,8 @@ defmodule Pleroma.Web.MediaProxy do
 
   def url(nil), do: nil
 
+  def url(""), do: nil
+
   def url(url = "/" <> _), do: url
 
   def url(url) do
@@ -15,10 +17,10 @@ defmodule Pleroma.Web.MediaProxy do
       base64 = Base.url_encode64(url, @base64_opts)
       sig = :crypto.hmac(:sha, secret, base64)
       sig64 = sig |> Base.url_encode64(@base64_opts)
-      filename = Path.basename(URI.parse(url).path)
+      filename = if path = URI.parse(url).path, do: "/" <> Path.basename(path), else: ""
 
       Keyword.get(config, :base_url, Pleroma.Web.base_url()) <>
-        "/proxy/#{sig64}/#{base64}/#{filename}"
+        "/proxy/#{sig64}/#{base64}#{filename}"
     end
   end
 
diff --git a/test/media_proxy_test.exs b/test/media_proxy_test.exs
new file mode 100644 (file)
index 0000000..c69ed7e
--- /dev/null
@@ -0,0 +1,113 @@
+defmodule Pleroma.MediaProxyTest do
+  use ExUnit.Case
+  import Pleroma.Web.MediaProxy
+
+  describe "when enabled" do
+    setup do
+      enabled = Pleroma.Config.get([:media_proxy, :enabled])
+
+      unless enabled do
+        Pleroma.Config.put([:media_proxy, :enabled], true)
+        on_exit(fn -> Pleroma.Config.put([:media_proxy, :enabled], enabled) end)
+      end
+
+      :ok
+    end
+
+    test "ignores invalid url" do
+      assert url(nil) == nil
+      assert url("") == nil
+    end
+
+    test "ignores relative url" do
+      assert url("/local") == "/local"
+      assert url("/") == "/"
+    end
+
+    test "ignores local url" do
+      local_url = Pleroma.Web.Endpoint.url() <> "/hello"
+      local_root = Pleroma.Web.Endpoint.url()
+      assert url(local_url) == local_url
+      assert url(local_root) == local_root
+    end
+
+    test "encodes and decodes URL" do
+      url = "https://pleroma.soykaf.com/static/logo.png"
+      encoded = url(url)
+
+      assert String.starts_with?(
+               encoded,
+               Pleroma.Config.get([:media_proxy, :base_url], Pleroma.Web.base_url())
+             )
+
+      assert String.ends_with?(encoded, "/logo.png")
+
+      assert decode_result(encoded) == url
+    end
+
+    test "encodes and decodes URL without a path" do
+      url = "https://pleroma.soykaf.com"
+      encoded = url(url)
+      assert decode_result(encoded) == url
+    end
+
+    test "encodes and decodes URL without an extension" do
+      url = "https://pleroma.soykaf.com/path/"
+      encoded = url(url)
+      assert String.ends_with?(encoded, "/path")
+      assert decode_result(encoded) == url
+    end
+
+    test "encodes and decodes URL and ignores query params for the path" do
+      url = "https://pleroma.soykaf.com/static/logo.png?93939393939&bunny=true"
+      encoded = url(url)
+      assert String.ends_with?(encoded, "/logo.png")
+      assert decode_result(encoded) == url
+    end
+
+    test "validates signature" do
+      secret_key_base = Pleroma.Config.get([Pleroma.Web.Endpoint, :secret_key_base])
+
+      on_exit(fn ->
+        Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], secret_key_base)
+      end)
+
+      encoded = url("https://pleroma.social")
+
+      Pleroma.Config.put(
+        [Pleroma.Web.Endpoint, :secret_key_base],
+        "00000000000000000000000000000000000000000000000"
+      )
+
+      [_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/")
+      assert decode_url(sig, base64) == {:error, :invalid_signature}
+    end
+  end
+
+  describe "when disabled" do
+    setup do
+      enabled = Pleroma.Config.get([:media_proxy, :enabled])
+
+      if enabled do
+        Pleroma.Config.put([:media_proxy, :enabled], false)
+
+        on_exit(fn ->
+          Pleroma.Config.put([:media_proxy, :enabled], enabled)
+          :ok
+        end)
+      end
+
+      :ok
+    end
+
+    test "does not encode remote urls" do
+      assert url("https://google.fr") == "https://google.fr"
+    end
+  end
+
+  defp decode_result(encoded) do
+    [_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/")
+    {:ok, decoded} = decode_url(sig, base64)
+    decoded
+  end
+end