From d4d295eae109d6c86c002d7ca833d296f3a93475 Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Tue, 28 May 2019 10:51:02 +0200
Subject: [PATCH] Add proxy route and proxify pics everywhere

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 lib/mobilizon_web/resolvers/event.ex          |  5 ++--
 lib/mobilizon_web/resolvers/group.ex          | 19 ++++++++----
 lib/mobilizon_web/resolvers/person.ex         | 30 ++++++++++++++++---
 lib/mobilizon_web/router.ex                   | 10 +++++++
 .../views/json_ld/object_view.ex              |  3 +-
 lib/service/export/feed.ex                    |  5 ++--
 lib/service/metadata/actor.ex                 |  4 ++-
 lib/service/metadata/event.ex                 |  6 +++-
 8 files changed, 65 insertions(+), 17 deletions(-)

diff --git a/lib/mobilizon_web/resolvers/event.ex b/lib/mobilizon_web/resolvers/event.ex
index 8cdac073e..3f0c3f29d 100644
--- a/lib/mobilizon_web/resolvers/event.ex
+++ b/lib/mobilizon_web/resolvers/event.ex
@@ -8,6 +8,7 @@ defmodule MobilizonWeb.Resolvers.Event do
   alias Mobilizon.Media.Picture
   alias Mobilizon.Actors.Actor
   alias Mobilizon.Users.User
+  alias MobilizonWeb.Resolvers.Person
 
   # We limit the max number of events that can be retrieved
   @event_max_limit 100
@@ -28,7 +29,7 @@ defmodule MobilizonWeb.Resolvers.Event do
         {:error, "Event with UUID #{uuid} not found"}
 
       event ->
-        {:ok, event}
+        {:ok, Map.put(event, :organizer_actor, Person.proxify_pictures(event.organizer_actor))}
     end
   end
 
@@ -116,7 +117,7 @@ defmodule MobilizonWeb.Resolvers.Event do
            }),
          participant <-
            Map.put(participant, :event, event)
-           |> Map.put(:actor, actor) do
+           |> Map.put(:actor, Person.proxify_pictures(actor)) do
       {:ok, participant}
     else
       {:is_owned, false} ->
diff --git a/lib/mobilizon_web/resolvers/group.ex b/lib/mobilizon_web/resolvers/group.ex
index 8a23d1a40..a0a0d78ce 100644
--- a/lib/mobilizon_web/resolvers/group.ex
+++ b/lib/mobilizon_web/resolvers/group.ex
@@ -7,16 +7,17 @@ defmodule MobilizonWeb.Resolvers.Group do
   alias Mobilizon.Users.User
   alias Mobilizon.Service.ActivityPub
   alias Mobilizon.Activity
+  alias MobilizonWeb.Resolvers.Person
   require Logger
 
   @doc """
   Find a group
   """
   def find_group(_parent, %{preferred_username: name}, _resolution) do
-    case ActivityPub.find_or_make_group_from_nickname(name) do
-      {:ok, actor} ->
-        {:ok, actor}
-
+    with {:ok, actor} <- ActivityPub.find_or_make_group_from_nickname(name),
+         actor <- Person.proxify_pictures(actor) do
+      {:ok, actor}
+    else
       _ ->
         {:error, "Group with name #{name} not found"}
     end
@@ -26,7 +27,8 @@ defmodule MobilizonWeb.Resolvers.Group do
   Lists all groups
   """
   def list_groups(_parent, %{page: page, limit: limit}, _resolution) do
-    {:ok, Actors.list_groups(page, limit)}
+    {:ok,
+     Actors.list_groups(page, limit) |> Enum.map(fn actor -> Person.proxify_pictures(actor) end)}
   end
 
   @doc """
@@ -141,7 +143,12 @@ defmodule MobilizonWeb.Resolvers.Group do
              actor_id: actor.id,
              role: role
            }) do
-      {:ok, %{parent: group, actor: actor, role: role}}
+      {:ok,
+       %{
+         parent: group |> Person.proxify_pictures(),
+         actor: actor |> Person.proxify_pictures(),
+         role: role
+       }}
     else
       {:is_owned, false} ->
         {:error, "Actor id is not owned by authenticated user"}
diff --git a/lib/mobilizon_web/resolvers/person.ex b/lib/mobilizon_web/resolvers/person.ex
index 28085054e..7867859f6 100644
--- a/lib/mobilizon_web/resolvers/person.ex
+++ b/lib/mobilizon_web/resolvers/person.ex
@@ -13,10 +13,10 @@ defmodule MobilizonWeb.Resolvers.Person do
   Find a person
   """
   def find_person(_parent, %{preferred_username: name}, _resolution) do
-    case ActivityPub.find_or_make_person_from_nickname(name) do
-      {:ok, actor} ->
-        {:ok, actor}
-
+    with {:ok, actor} <- ActivityPub.find_or_make_person_from_nickname(name),
+         actor <- proxify_pictures(actor) do
+      {:ok, actor}
+    else
       _ ->
         {:error, "Person with name #{name} not found"}
     end
@@ -135,4 +135,26 @@ defmodule MobilizonWeb.Resolvers.Person do
         {:error, "Actor id is not owned by authenticated user"}
     end
   end
+
+  def proxify_pictures(%Actor{} = actor) do
+    actor
+    |> proxify_avatar
+    |> proxify_banner
+  end
+
+  @spec proxify_avatar(Actor.t()) :: Actor.t()
+  defp proxify_avatar(%Actor{avatar: %{url: avatar_url} = avatar} = actor) do
+    actor |> Map.put(:avatar, avatar |> Map.put(:url, MobilizonWeb.MediaProxy.url(avatar_url)))
+  end
+
+  @spec proxify_avatar(Actor.t()) :: Actor.t()
+  defp proxify_avatar(%Actor{} = actor), do: actor
+
+  @spec proxify_banner(Actor.t()) :: Actor.t()
+  defp proxify_banner(%Actor{banner: %{url: banner_url} = banner} = actor) do
+    actor |> Map.put(:banner, banner |> Map.put(:url, MobilizonWeb.MediaProxy.url(banner_url)))
+  end
+
+  @spec proxify_banner(Actor.t()) :: Actor.t()
+  defp proxify_banner(%Actor{} = actor), do: actor
 end
diff --git a/lib/mobilizon_web/router.ex b/lib/mobilizon_web/router.ex
index 2d7e1d3af..e70a0ccbb 100644
--- a/lib/mobilizon_web/router.ex
+++ b/lib/mobilizon_web/router.ex
@@ -39,6 +39,9 @@ defmodule MobilizonWeb.Router do
     plug(:put_secure_browser_headers)
   end
 
+  pipeline :remote_media do
+  end
+
   scope "/api" do
     pipe_through(:graphql)
 
@@ -94,6 +97,13 @@ defmodule MobilizonWeb.Router do
     post("/inbox", ActivityPubController, :inbox)
   end
 
+  scope "/proxy/", MobilizonWeb do
+    pipe_through(:remote_media)
+
+    get("/:sig/:url", MediaProxyController, :remote)
+    get("/:sig/:url/:filename", MediaProxyController, :remote)
+  end
+
   if Mix.env() == :dev do
     # If using Phoenix
     forward("/sent_emails", Bamboo.SentEmailViewerPlug)
diff --git a/lib/mobilizon_web/views/json_ld/object_view.ex b/lib/mobilizon_web/views/json_ld/object_view.ex
index 2ef2e3765..9bfb028f8 100644
--- a/lib/mobilizon_web/views/json_ld/object_view.ex
+++ b/lib/mobilizon_web/views/json_ld/object_view.ex
@@ -5,6 +5,7 @@ defmodule MobilizonWeb.JsonLD.ObjectView do
   alias Mobilizon.Actors.Actor
   alias Mobilizon.Addresses.Address
   alias MobilizonWeb.JsonLD.ObjectView
+  alias MobilizonWeb.MediaProxy
 
   def render("event.json", %{event: %Event{} = event}) do
     # TODO: event.description is actually markdown!
@@ -25,7 +26,7 @@ defmodule MobilizonWeb.JsonLD.ObjectView do
     json_ld =
       if event.picture do
         Map.put(json_ld, "image", [
-          event.picture.file.url
+          event.picture.file.url |> MediaProxy.url()
         ])
       else
         json_ld
diff --git a/lib/service/export/feed.ex b/lib/service/export/feed.ex
index f525961b6..65eb685f0 100644
--- a/lib/service/export/feed.ex
+++ b/lib/service/export/feed.ex
@@ -13,6 +13,7 @@ defmodule Mobilizon.Service.Export.Feed do
   import MobilizonWeb.Gettext
   alias MobilizonWeb.Router.Helpers, as: Routes
   alias MobilizonWeb.Endpoint
+  alias MobilizonWeb.MediaProxy
   require Logger
 
   @version Mix.Project.config()[:version]
@@ -76,14 +77,14 @@ defmodule Mobilizon.Service.Export.Feed do
 
     feed =
       if actor.avatar do
-        Feed.icon(feed, actor.avatar.url)
+        feed |> Feed.icon(actor.avatar.url |> MediaProxy.url())
       else
         feed
       end
 
     feed =
       if actor.banner do
-        Feed.logo(feed, actor.banner.url)
+        feed |> Feed.logo(actor.banner.url |> MediaProxy.url())
       else
         feed
       end
diff --git a/lib/service/metadata/actor.ex b/lib/service/metadata/actor.ex
index 4c83e627f..d6bb357a1 100644
--- a/lib/service/metadata/actor.ex
+++ b/lib/service/metadata/actor.ex
@@ -1,6 +1,7 @@
 defimpl Mobilizon.Service.Metadata, for: Mobilizon.Actors.Actor do
   alias Phoenix.HTML.Tag
   alias Mobilizon.Actors.Actor
+  alias MobilizonWeb.MediaProxy
 
   def build_tags(%Actor{} = actor) do
     tags = [
@@ -15,7 +16,8 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Actors.Actor do
     if is_nil(actor.avatar) do
       tags
     else
-      tags ++ [Tag.tag(:meta, property: "og:image", content: actor.avatar.url)]
+      tags ++
+        [Tag.tag(:meta, property: "og:image", content: actor.avatar.url |> MediaProxy.url())]
     end
   end
 end
diff --git a/lib/service/metadata/event.ex b/lib/service/metadata/event.ex
index 773af7aa7..91c801b45 100644
--- a/lib/service/metadata/event.ex
+++ b/lib/service/metadata/event.ex
@@ -3,6 +3,7 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
   alias Phoenix.HTML.Tag
   alias Mobilizon.Events.Event
   alias MobilizonWeb.JsonLD.ObjectView
+  alias MobilizonWeb.MediaProxy
 
   def build_tags(%Event{} = event) do
     tags = [
@@ -18,7 +19,10 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
       else
         tags ++
           [
-            Tag.tag(:meta, property: "og:image", content: event.picture.file.url)
+            Tag.tag(:meta,
+              property: "og:image",
+              content: event.picture.file.url |> MediaProxy.url()
+            )
           ]
       end