1

システム用の管理ツールアプリを構築しています。すべてのユーザーが行ったすべてのアクションを記録したい。

これが私がしたことです

defmodule AdminToolWeb.UserController do
  use AdminToolWeb, :controller
  
  ...

  def delete(conn, %{"id" => id}) do
    current_user = Guardian.Plug.current_resource(conn)

    with %User{} <- user = Accounts.get_user(id) do
      Accounts.delete_user(user)

      conn
      |> put_flash(:info, "#{user.id} deleted.")
      |> Activities.log(current_user)
      |> redirect(to: Routes.user_path(conn, :index))
    end
  end

  ...
end

|> Activity.log(current_user)問題は、アプリにあるすべてのコントローラーのすべてのアクションをパイプ処理する必要があることです。

このようなものを実装する方法はありますか? Controller -> (ActivityLogPlugOfSorts) -> View カスタムプラグを使用して、このように呼び出しますか?

defmodule AdminToolWeb.UserController do
  use AdminToolWeb, :controller
  import AdminToolWeb.Plugs.Activities

  plug :log

...

ただし、コントローラーとビューの間で呼び出す必要があります。

または、代わりに View モジュール内に関数を配置する必要がありますか?

もっと良い方法があることを願っています。

4

1 に答える 1

1

ここで探しているのは、実際にコントローラー レベルで直接挿入できるコントローラー プラグです。それらはコントローラ アクションのに実行されるため、プラグが実行されたときに、試行されたアクションが成功するかどうかを知る機会はありません。ただし、コントローラー プラグを使用して、コントローラー アクションの(ただし、応答が送信される前) に実行されるコールバックをセットアップできます。例は次のとおりです。

defmodule HelloWeb.Plugs.ActionLogger do
  import Plug.Conn
  require Logger

  def init(default), do: default

  def call(conn, _default) do
    register_before_send(conn, fn conn ->
      if (response_code_2xx?(conn) do
        Logger.info("action taken: #{extract_action(conn)}")
      end
      conn
    end)
  end
end

whereresponse_code_2xx?/1extract_action/1は読者の練習問題として残しておきます。

于 2021-01-25T14:52:05.303 に答える