X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fweb.ex;h=ae7c94640f83065a91f3cc3e7a68d9540c879845;hb=24f760c2f732465151655fd4cd69cc149546b29f;hp=1aa86f64514e3d8d9af578f65aac3b07eddbe7dd;hpb=89fbed88212657e3dcd4bbcb2c0718b07802037f;p=akkoma diff --git a/lib/pleroma/web/web.ex b/lib/pleroma/web/web.ex index 1aa86f645..ae7c94640 100644 --- a/lib/pleroma/web/web.ex +++ b/lib/pleroma/web/web.ex @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web do @@ -23,8 +23,46 @@ defmodule Pleroma.Web do def controller do quote do use Phoenix.Controller, namespace: Pleroma.Web + import Plug.Conn - import Pleroma.Web.{Gettext, Router.Helpers} + import Pleroma.Web.Gettext + import Pleroma.Web.Router.Helpers + import Pleroma.Web.TranslationHelpers + + alias Pleroma.Plugs.PlugHelper + + plug(:set_put_layout) + + defp set_put_layout(conn, _) do + put_layout(conn, Pleroma.Config.get(:app_layout, "app.html")) + end + + # Marks a plug intentionally skipped and blocks its execution if it's present in plugs chain + defp skip_plug(conn, plug_module) do + try do + plug_module.ensure_skippable() + rescue + UndefinedFunctionError -> + raise "#{plug_module} is not skippable. Append `use Pleroma.Web, :plug` to its code." + end + + PlugHelper.append_to_skipped_plugs(conn, plug_module) + end + + # Here we can apply before-action hooks (e.g. verify whether auth checks were preformed) + defp action(conn, params) do + if Pleroma.Plugs.AuthExpectedPlug.auth_expected?(conn) && + not PlugHelper.plug_called_or_skipped?(conn, Pleroma.Plugs.OAuthScopesPlug) do + conn + |> render_error( + :forbidden, + "Security violation: OAuth scopes check was neither handled nor explicitly skipped." + ) + |> halt() + else + super(conn, params) + end + end end end @@ -37,13 +75,43 @@ defmodule Pleroma.Web do # Import convenience functions from controllers import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1] - import Pleroma.Web.{ErrorHelpers, Gettext, Router.Helpers} + import Pleroma.Web.ErrorHelpers + import Pleroma.Web.Gettext + import Pleroma.Web.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})}\n" <> + Exception.format(:error, error, __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 def router do quote do use Phoenix.Router + # credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse import Plug.Conn import Phoenix.Controller end @@ -51,11 +119,32 @@ defmodule Pleroma.Web do def channel do quote do + # credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse use Phoenix.Channel import Pleroma.Web.Gettext end end + def plug do + quote do + alias Pleroma.Plugs.PlugHelper + + def ensure_skippable, do: :noop + + @impl Plug + @doc "If marked as skipped, returns `conn`, and calls `perform/2` otherwise." + def call(%Plug.Conn{} = conn, options) do + if PlugHelper.plug_skipped?(conn, __MODULE__) do + conn + else + conn + |> PlugHelper.append_to_called_plugs(__MODULE__) + |> perform(options) + end + end + end + end + @doc """ When used, dispatch to the appropriate controller/view/etc. """