Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Papertrail: records with nil whodunnit values and object_changes in logs

I've set papertrail to only record changes containing a whodunnit value/when an admin makes a change by using the below condition in my model:

has_paper_trail if: proc { |model| PaperTrail.request.whodunnit.present? }

However I've noticed there are still a decent amount of records being stored with empty whodunnit values. From having a look at the records, these seem to be mostly 'update' actions all having empty object changes for some reason. I am unsure as to why the value is empty, or how it would get saved at all considering the above condition.

I am getting whodunnit values from warden in my application controller using:

def user_for_paper_trail
  request.env['warden']&.user(:admin)&.id
end

Has anyone come across similar behaviour before?

like image 666
L457 Avatar asked Nov 06 '22 03:11

L457


1 Answers

Adding a source_location and command field to your papertrail versions table will help you:

  1. track what command is causing the nil whodunnit changes.
  2. Ensure you record correctly changes initiated by a rake task or rails console.

To do this, create a migration to add the source_location and command fields to your Versions table:


class AddSourceLocationAndCommandToVersions < ActiveRecord::Migration
  def change
    add_column :versions, :source_location, :text
    add_column :versions, :command, :text
  end
end

I have the following set up in my papertrail.rb. I am using the JSON serializer but these changes may work with the normal serializer. The code after the serializer declaration is what is of interest to you:

require "paper_trail/frameworks/rails"
require "paper_trail"

# the following line is required for PaperTrail >= 4.0.0 with Rails
PaperTrail::Rails::Engine.eager_load!

PaperTrail.config.enabled = true
PaperTrail.serializer = PaperTrail::Serializers::JSON

# Store some metadata about where the change came from, even for rake tasks, etc.
# See: https://github.com/paper-trail-gem/paper_trail/wiki/Setting-whodunnit-in-the-rails-console
def PaperTrail.set_global_metadata
  request.controller_info ||= {}
  request.controller_info[:command] ||= "#{File.basename($PROGRAM_NAME)} #{ARGV.join ' '} (#{$PID})"
  request.controller_info[:source_location] = caller.find { |line|
    line.starts_with? Rails.root.to_s and
   !line.starts_with? __FILE__
  }
end

# Defer evaluation in case we're using spring loader (otherwise it would be something like "spring app    | app | started 13 secs ago | development")
# There's no way to set up deferred evaluation of PaperTrail.request.controller_info from here like
# we can with whodunnit, so abuse that property of PaperTrail.request.whodunnit to set other
# metadata. Reserve the whodunnit field for storing the actual name or id of the human who made the
# change.
PaperTrail.request.whodunnit = ->() {
  PaperTrail.set_global_metadata
  if Rails.const_defined?("Console") || $rails_rake_task
    "#{`whoami`.strip}: console"
  else
    "#{`whoami`.strip}: #{File.basename($PROGRAM_NAME)} #{ARGV.join ' '}"
  end
}

Rails.application.configure do
  console do
    PaperTrail.request.controller_info = { command: "rails console" }
    PaperTrail.request.whodunnit = ->() {
      PaperTrail.set_global_metadata

      @paper_trail_whodunnit ||= (
        if Rails.const_defined?("Console") || $rails_rake_task
          "#{`whoami`.strip}: console"
        else
          "#{`whoami`.strip}: #{File.basename($PROGRAM_NAME)} #{ARGV.join ' '}"
        end
      )
    }
  end
end

Note that in any place where record creation occurs outside of a request, you can manually set the whodunnit value to something specific if you don't want it blank. E.g. in my seed file I do the following:


class SeedCreator
  def initialize
    PaperTrail.request.whodunnit = ->() {
      PaperTrail.set_global_metadata # save source_location & command
      "seed" # set whodunnit value to "seed"
    }
    create_campaign
    create_users
    # more seeding of models....
  end
end

In addition to improving the quality of your Papertrail table (knowing which command triggered a record update), this config should help you identify where phantom whodunnits are being saved.

like image 191
Kelsey Hannan Avatar answered Nov 10 '22 01:11

Kelsey Hannan