Views: wrap activity rendering in a rescue
authorhref <href@random.sh>
Sun, 27 Jan 2019 18:15:35 +0000 (19:15 +0100)
committerhref <href@random.sh>
Sun, 27 Jan 2019 18:16:20 +0000 (19:16 +0100)
this avoids complete timeline breakage when an activity fucks up
rendering.

lib/pleroma/web/mastodon_api/views/status_view.ex
lib/pleroma/web/twitter_api/views/activity_view.ex
lib/pleroma/web/web.ex

index 7a384e941bfb6ac50389508284a819cd169e824f..0f26794441e78a03ece52daadf840d1b97ca6ff0 100644 (file)
@@ -49,7 +49,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
     replied_to_activities = get_replied_to_activities(opts.activities)
 
     opts.activities
-    |> render_many(
+    |> safe_render_many(
       StatusView,
       "status.json",
       Map.put(opts, :replied_to_activities, replied_to_activities)
index e0a52d94abcf5128bb56bc78413fb777206de4a4..a01ee00106f47fbd761c92fbdb0ecfe032431a59 100644 (file)
@@ -114,7 +114,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
       |> Map.put(:context_ids, context_ids)
       |> Map.put(:users, users)
 
-    render_many(
+    safe_render_many(
       opts.activities,
       ActivityView,
       "activity.json",
index 74b13f929def29a15990773044369d99f6fd8eca..30558e6926ad601355372e544e688e629a28b682 100644 (file)
@@ -38,6 +38,33 @@ defmodule Pleroma.Web do
       import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
 
       import Pleroma.Web.{ErrorHelpers, Gettext, Router.Helpers}
+
+      require Logger
+
+      @doc "Same as `render/3` but wrapped in a rescue block"
+      def safe_render(view, template, assigns \\ %{}) do
+        Phoenix.View.render(view, template, assigns)
+      rescue
+        error ->
+          Logger.error(
+            "#{__MODULE__} failed to render #{inspect({view, template})}: #{inspect(error)}"
+          )
+
+          Logger.error(inspect(__STACKTRACE__))
+          nil
+      end
+
+      @doc """
+      Same as `render_many/4` but wrapped in rescue block.
+      """
+      def safe_render_many(collection, view, template, assigns \\ %{}) do
+        Enum.map(collection, fn resource ->
+          as = Map.get(assigns, :as) || view.__resource__
+          assigns = Map.put(assigns, as, resource)
+          safe_render(view, template, assigns)
+        end)
+        |> Enum.filter(& &1)
+      end
     end
   end