X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fweb.ex;h=bf48ce26c8380202b9208095aed92f9d072abf7a;hb=2430b9bf90d6fde71885f5f0f8be767526be6208;hp=6873465544b19fab1c9d31f88689708a52cbf87f;hpb=47c20ab79635257f4a8dcd9886821d10276516a3;p=akkoma diff --git a/lib/pleroma/web/web.ex b/lib/pleroma/web/web.ex index 687346554..bf48ce26c 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-2019 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web do @@ -29,11 +29,45 @@ defmodule Pleroma.Web do 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.skip_plug(conn) + rescue + UndefinedFunctionError -> + raise "#{plug_module} is not skippable. Append `use Pleroma.Web, :plug` to its code." + end + end + + # Executed just before actual controller action, invokes before-action hooks (callbacks) + defp action(conn, params) do + with %Plug.Conn{halted: false} <- maybe_halt_on_missing_oauth_scopes_check(conn) do + super(conn, params) + end + end + + # Halts if authenticated API action neither performs nor explicitly skips OAuth scopes check + defp maybe_halt_on_missing_oauth_scopes_check(conn) 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 + conn + end + end end end @@ -96,6 +130,35 @@ defmodule Pleroma.Web do end end + def plug do + quote do + alias Pleroma.Plugs.PlugHelper + + @doc """ + Marks a plug intentionally skipped and blocks its execution if it's present in plugs chain. + """ + def skip_plug(conn) do + PlugHelper.append_to_private_list( + conn, + PlugHelper.skipped_plugs_list_id(), + __MODULE__ + ) + end + + @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_private_list(PlugHelper.called_plugs_list_id(), __MODULE__) + |> perform(options) + end + end + end + end + @doc """ When used, dispatch to the appropriate controller/view/etc. """