Хук запуска транзакции Rails - PullRequest
0 голосов
/ 06 июля 2018

Я хочу перевести базу данных своей компании с аудита на уровне приложения на аудит на уровне базы данных. Я буду использовать триггер 91audit, подробно описанный здесь: https://github.com/2ndQuadrant/audit-trigger/blob/master/audit.sql

Проблема с аудитом на уровне БД заключается в том, что он фактически не записывает текущего пользователя, а записывает пользователя postgresql.

Недостатком аудита на уровне приложений является то, что я должен выполнять каждую транзакцию через веб-приложение для проверки изменения (не работает, если у меня несколько приложений в одной базе данных)

Я нашел действительно интересное решение здесь: http://schinckel.net/2014/06/01/in-database-audit-trail/

Решение основано на обновлении / вставке строки во временную таблицу в начале каждой транзакции.

сейчас

Чтобы это работало для меня, я хочу добавить ловушку к рельсам, чтобы обновить эту временную таблицу при любом вызове сохранения, обновления, уничтожения или удаления.

Мой вопрос:

Существует ли хук верхнего уровня transaction-start для Rails 5.2+; желательно что-то, что я могу установить внутри и инициализатором или в ApplicationRecord?

Моей первой мыслью было бы добавить инициализатор, но я понятия не имею, к чему я подключусь

Мой план резервного копирования - переопределить ApplicationRecord.transaction

class ApplicationRecord < ActiveRecord::Base
  def self.transaction(*args)
    super(*args) do
      if Current.user
        ActiveRecord::Base.connection.execute(%Q(
          CREATE TEMP TABLE IF NOT EXISTS
          "_app_user" (user_id integer, ip_address inet);

          UPDATE
            _app_user
          SET
            user_id=#{Current.user.id},
            ip_address='#{Current.ip_address}';

          INSERT INTO
            _app_user (user_id, ip_address)
          SELECT
            #{Current.user.id}, '#{Current.ip_address}'
          WHERE NOT EXISTS (SELECT * FROM _app_user);
        ))
      end

      yield
    end
  end
end

1 Ответ

0 голосов
/ 06 июля 2018

Переопределение ActiveRecord.transaction, кажется, работает просто отлично

class ApplicationRecord < ActiveRecord::Base
  def self.transaction(*args)
    super(*args) do
      if Current.user
        ip = Current.ip_address ? "'#{Current.ip_address}'" : 'NULL'
        ActiveRecord::Base.connection.execute <<-SQL
          CREATE TEMP TABLE IF NOT EXISTS
            "_app_user" (user_id integer, user_type text, ip_address inet);

          UPDATE
            _app_user
          SET
            user_id=#{Current.user.id},
            user_type='#{Current.user.class.to_s}',
            ip_address=#{ip};

          INSERT INTO
            _app_user (user_id, user_type, ip_address)
          SELECT
            #{Current.user.id},
            '#{Current.user.class.to_s}',
            #{ip}
          WHERE NOT EXISTS (SELECT * FROM _app_user);
        SQL
      end

      yield
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...