auditedというgemを使って、監査ログを保存するようにしたいと思い、現在調査中。
大体はよさそうなので、採用したいと思っているのだけれど、困ったのが、rails console
とかでデータ変更されたとき。データ変更の履歴は残るものの、誰がやったかがわからない。
流石にそれだと万が一rails console
経由で変な処理してしまったら困るので、誰かは分からずともrails console
経由であることくらいはわかるようにしたいということで、設定してみました。
rails consoleであることをどうやって検知するか?
これが全然わからなかったのですが、stackoverflowにありました。
これによると、defined?(::Rails::Server)
でいけるとあります。
実際にやってみると…。
bin/rails c Loading development environment (Rails 6.0.3.6) [1] pry(main)> defined?(::Rails::Server) => nil
なるほど、consoleだと::Rails::Server
の定義を読み込まないということですね。
ちなみにRailsの初期化プロセスはRailsガイドにあるので、こちらも読むと参考になります。最初はこれを読んでどこかで処理を差し込むところはないか?を探ってました。
auditedのinitializerを定義する
config/initializers/audited.rb
を作ります。
unless defined?(::Rails::Server) Audited.store[:audited_user] = "console" end
ということで、これでめでたし、めでたし…とはなりません😢
rake taskのときにも::Rails::Server
は読みこまれないので、rake taskでもusernameが入ってしまいました。
純粋にrails console
であることを検知するにはどうしたらいいのか…。
rake taskであることを検知する
これもまたstackoverflowでヒットしました。
Rake.application.top_level_tasks.empty?
をすることで、現在の処理がrake task経由であることがわかるようです。
ということで、config/initializers/audited.rb
を修正。
unless defined?(::Rails::Server) if Rake.application.top_level_tasks.empty? Audited.store[:audited_user] = "console" else Audited.store[:audited_user] = "rake-task" end end
これで、今のところ問題なさそう!👍
と思ったけれど、この記事を書いている最中に、rails runner
のことを考慮できてないやんって気付いた…。ダメだ…😵
Railsの設定で可能だった
ここにきて、神速さんから素晴らしい情報をもらった。
`config.console` を使うと解決したりします?https://t.co/ggRSJz1vJz
— 神速 (@sinsoku_listy) 2021年4月14日
これを設定したら簡単、かつ、わかりやすかった。ダメ元でrunner do
も付けてみたらrails runnerの時の設定もうまくいった(ぇ。
しかし、rake taskのときの検出方法がRailsの設定ではわからなかったので、さっきのやつを使うことに。
Rails.application.configure do console do Audited.store[:audited_user] = "console" end runner do Audited.store[:audited_user] = "runner" end end unless defined?(::Rails::Server) if Rake.application.top_level_tasks.present? Audited.store[:audited_user] = "rake-task" end end
これでバッチリでした!👍
[3] pry(main)> hoge = Hoge.find(1) [4] pry(main)> hoge.name => "あああ" [5] pry(main)> hoge.update(name: "アアア") [6] pry(main)> Audited::Audit.last Audited::Audit Load (1.3ms) SELECT "audits".* FROM "audits" ORDER BY "audits"."id" DESC LIMIT 1 => #<Audited::Audit:0x000055b996469a88 id: 380, auditable_id: 1, auditable_type: "Hoge", associated_id: nil, associated_type: nil, user_id: nil, user_type: nil, username: "console", # <= ここが重要!! action: "update", audited_changes: {"name"=>["あああ", "アアア"]}, version: 1, comment: nil, remote_address: nil, request_uuid: "4f057afe-2edc-4614-88fd-0a17a7b3d93d", created_at: Wed, 14 Apr 2021 18:19:19 JST +09:00>