diff --git a/Gemfile b/Gemfile
index bf70e13..9ec06ca 100644
--- a/Gemfile
+++ b/Gemfile
@@ -17,6 +17,7 @@ gem "image_processing", "~> 1.12"
gem "devise"
gem "devise-i18n"
+gem "paper_trail"
gem "slack-notifier"
gem "administrate-field-active_storage"
gem "administrate-field-enumerize"
diff --git a/Gemfile.lock b/Gemfile.lock
index 89105c8..b0edbd3 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -175,6 +175,9 @@ GEM
mini_portile2 (~> 2.6.1)
racc (~> 1.4)
orm_adapter (0.5.0)
+ paper_trail (12.0.0)
+ activerecord (>= 5.2)
+ request_store (~> 1.1)
parallel (1.20.1)
parser (3.0.2.0)
ast (~> 2.4.1)
@@ -235,6 +238,8 @@ GEM
rb-inotify (0.10.1)
ffi (~> 1.0)
regexp_parser (2.1.1)
+ request_store (1.5.0)
+ rack (>= 1.4)
responders (3.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
@@ -354,6 +359,7 @@ DEPENDENCIES
image_processing (~> 1.12)
listen (~> 3.3)
money-rails
+ paper_trail
pg (~> 1.1)
pry-byebug
puma (~> 5.0)
diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb
index aed0512..bb63a55 100644
--- a/app/controllers/admin/application_controller.rb
+++ b/app/controllers/admin/application_controller.rb
@@ -2,5 +2,12 @@
module Admin
class ApplicationController < Administrate::ApplicationController
before_action :authenticate_admin_user!
+ before_action :set_paper_trail_whodunnit
+
+ # used by #set_paper_trail_whodunnit
+ def current_user
+ # add admin prefix to differentiate from a customer
+ "admin/#{current_admin_user.id}"
+ end
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d970904..a30d4c6 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
class ApplicationController < ActionController::Base
+ before_action :set_paper_trail_whodunnit
before_action :configure_devise_permitted_parameters, if: :devise_controller?
protected
diff --git a/app/models/balance.rb b/app/models/balance.rb
index 7f98371..1020d1e 100644
--- a/app/models/balance.rb
+++ b/app/models/balance.rb
@@ -22,6 +22,8 @@
# fk_rails_... (user_id => users.id)
#
class Balance < ApplicationRecord
+ include Trackable
+
belongs_to :user
belongs_to :currency
diff --git a/app/models/concerns/trackable.rb b/app/models/concerns/trackable.rb
new file mode 100644
index 0000000..810e161
--- /dev/null
+++ b/app/models/concerns/trackable.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+module Trackable
+ extend ActiveSupport::Concern
+
+ included do
+ has_paper_trail
+ end
+end
diff --git a/app/models/fiat_balance.rb b/app/models/fiat_balance.rb
index b64c62a..3f297a2 100644
--- a/app/models/fiat_balance.rb
+++ b/app/models/fiat_balance.rb
@@ -20,6 +20,8 @@
# fk_rails_... (user_id => users.id)
#
class FiatBalance < ApplicationRecord
+ include Trackable
+
belongs_to :user
monetize :amount_cents
diff --git a/db/migrate/20210817233439_create_versions.rb b/db/migrate/20210817233439_create_versions.rb
new file mode 100644
index 0000000..438cf98
--- /dev/null
+++ b/db/migrate/20210817233439_create_versions.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+# This migration creates the `versions` table, the only schema PT requires.
+# All other migrations PT provides are optional.
+class CreateVersions < ActiveRecord::Migration[6.1]
+ # The largest text column available in all supported RDBMS is
+ # 1024^3 - 1 bytes, roughly one gibibyte. We specify a size
+ # so that MySQL will use `longtext` instead of `text`. Otherwise,
+ # when serializing very large objects, `text` might not be big enough.
+ TEXT_BYTES = 1_073_741_823
+
+ def change
+ create_table(:versions) do |t|
+ t.string(:item_type, { null: false })
+ t.bigint(:item_id, null: false)
+ t.string(:event, null: false)
+ t.string(:whodunnit)
+ t.text(:object, limit: TEXT_BYTES)
+
+ t.datetime(:created_at)
+ end
+ add_index(:versions, [:item_type, :item_id])
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 89afce2..89ef41a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2021_08_16_174637) do
+ActiveRecord::Schema.define(version: 2021_08_17_233439) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -138,6 +138,16 @@ ActiveRecord::Schema.define(version: 2021_08_16_174637) do
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
+ create_table "versions", force: :cascade do |t|
+ t.string "item_type", null: false
+ t.bigint "item_id", null: false
+ t.string "event", null: false
+ t.string "whodunnit"
+ t.text "object"
+ t.datetime "created_at"
+ t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
+ end
+
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "balances", "currencies"
diff --git a/erd.svg b/erd.svg
index 28dd21c..25c19e1 100644
--- a/erd.svg
+++ b/erd.svg
@@ -69,8 +69,8 @@
m_Currency->m_Balance
-
-
+
+
@@ -79,7 +79,7 @@
-
+
m_SellCryptoOrder
SellCryptoOrder
@@ -102,7 +102,7 @@
-
+
m_StakeOrder
StakeOrder
@@ -137,8 +137,25 @@
user_id
integer (8) ∗ FK
+
+
+m_PaperTrail::Version
+
+PaperTrail::Version
+
+event
+string ∗
+item_id
+integer (8) ∗
+item_type
+string ∗
+object
+text
+whodunnit
+string
+
-
+
m_User
User
@@ -188,7 +205,7 @@
-
+
m_UserDocument
UserDocument