0

我正在尝试编写一个应用程序来跟踪法律案件请求。主要模型是 Case,其中包含has_manySubjects、Keywords、Notes 和 Evidences(反过来又是has_manyCustodyLogs)。由于该应用程序与法律相关,因此有一些不同寻常的要求:

  • 必须记录 CRUD 操作,包括操作是什么、参与者是谁以及操作发生的时间
  • 需要有某种方法来验证数据(即记录记录的 MD5 校验和)
  • 一些数据应该是一次性写入的(即应用程序可以创建一个审计日志条目,但此后不能在应用程序内编辑或删除该日志)
  • 可能应该在整个嵌套过程中记录对关联对象的更改。例如,将 CustodyLog 添加到一个 Evidence 应该有一个日志用于它自己,一个日志用于它的 Evidence,一个日志用于父案例。这是为了确保 Case 的上次更新时间戳准确地反映了真实的上次更新,而不仅仅是 Case 模型数据本身更改的上次时间。

我有一些这样的工作,但我遇到了一个问题。身份验证由外部 Web 单点登录服务处理,因此登录用户 ID 的唯一可见性是在请求变量中。例如,如果我通过回调将审计日志记录在模型中,我可以相当确定所有数据修改都已记录,但模型对请求变量不可见,因此我无法记录用户 ID。这也确保了对状态机(当前使用 state_machine 插件)的更改被记录下来。

另一方面,如果我将审计日志记录放在应用程序控制器中,我将无法确保记录所有 CRUD 操作(例如,调用 Subject.create 的案例模型中的代码不会被记录) . 我也认为我会失去状态变化。

有没有办法确保在整个关联树中记录所有 CRUD 操作,以便记录登录用户的用户 ID?

4

1 回答 1

0

必须记录 CRUD 操作,包括操作是什么、参与者是谁以及操作发生的时间

这可以通过 ActiveRecord::Callbacks 和 attr_accessor 字段来解决。

在需要记录的任何模型中添加以下内容。

  attr_accessor :modifier_id, :modifier

  valiadate :valid_user
  before_validate :populate_modifier
  before_save :write_save_attempted_to_audit_log
  after_save :write_save_completed_to_audit_log

  def populate_modifier
    self.modifier = User.find_by_id(modifier_id) unless modifier
  end 

  def valid_user
    unless modifier
      errors.add(:modifiers_user_id, "Unknown user attempted to modify this record") 
      write_unauthorized_modification_to_audit_log
    end
  end

  def write_save_attempted_to_audit_log
    # announce that user is attempting to save a record with timestamp to audit log
    # use ActiveRecord::Dirty.changes to show the change the might be made
  end

  def write_save_competed_to_audit_log
    # announce that user has successfully changed the record with timestamp to audit log
  end

  def write_unauthorized_modification
    # announce that a change was attempted without a user
  end

因为您可能会在一些模型中使用它,所以您可以将其抽象为插件,并仅在需要时通过方法调用(如audit_changes. 请参阅任何acts_as 插件以获取有关如何完成此操作的灵感。

在控制器中,您需要记住@thing.modifier = @current_user在尝试保存之前添加。


需要有某种方法来验证数据(即记录记录的 MD5 校验和)

至于校验和......操作?您可以覆盖检查以以一致的方式打印包含记录中所有信息的字符串,然后为此生成校验和。当您使用它时,不妨将其添加到审计日志中,作为写入日志方法的一部分。


一些数据应该是一次性写入的(即应用程序可以创建一个审计日志条目,但此后不能在应用程序内编辑或删除该日志)

将每个访问日志写入具有确定性名称 ( "/logs/audits/#{class}/#{id}/#{timestamp}") 的单独文件,并在保存后删除写入权限。File.chmod(0555, access_log_file)


可能应该在整个嵌套过程中记录对关联对象的更改。例如,将 CustodyLog 添加到一个 Evidence 应该有一个日志用于它自己,一个日志用于它的 Evidence,一个日志用于父案例。这是为了确保 Case 的上次更新时间戳准确地反映了真实的上次更新,而不仅仅是 Case 模型数据本身更改的上次时间。

至于第四个要求。如果您在任何嵌套关系上使用accepts_nested_attributes_for,这将首先自动进入我的解决方案。并且 :autosave => true 用于 belongs_to 关系。


如果您将校验和保存到审计日志中,您可以在 before_save 方法中进行检查,以确保您正在处理的对象未被篡改。只需检查对象的最新审计日志并匹配校验和即可。

于 2009-10-23T22:34:22.093 回答