Credo fixes.
[akkoma] / lib / pleroma / web / web.ex
index 1af29ce788bcdadffb18871f372e1e76c256c252..bf48ce26c8380202b9208095aed92f9d072abf7a 100644 (file)
@@ -37,15 +37,26 @@ defmodule Pleroma.Web do
         put_layout(conn, Pleroma.Config.get(:app_layout, "app.html"))
       end
 
-      # Marks a plug as intentionally skipped
-      #   (states that the plug is not called for a good reason, not by a mistake)
+      # Marks a plug intentionally skipped and blocks its execution if it's present in plugs chain
       defp skip_plug(conn, plug_module) do
-        PlugHelper.append_to_skipped_plugs(conn, plug_module)
+        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
 
-      # Here we can apply before-action hooks (e.g. verify whether auth checks were preformed)
+      # Executed just before actual controller action, invokes before-action hooks (callbacks)
       defp action(conn, params) do
-        if conn.private[:auth_expected] &&
+        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(
@@ -54,7 +65,7 @@ defmodule Pleroma.Web do
           )
           |> halt()
         else
-          super(conn, params)
+          conn
         end
       end
     end
@@ -119,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.
   """