我正在尝试编写一个应用程序来跟踪法律案件请求。主要模型是Case,has_many
主题,关键词,注释和证据(反过来,has_many
CustodyLogs)。由于申请与法律有关,因此有一些不寻常的要求:
我有点工作,但我遇到了问题。身份验证由外部Web单点登录服务处理,因此对登录用户的ID的唯一可见性在请求变量中。例如,如果我通过回调将审计日志记录放入模型中,我可以相当确定所有数据修改都已记录,但模型对请求变量没有可见性,因此我无法记录用户ID。这还可以确保记录对状态机(当前使用state_machine插件)的更改。
另一方面,如果我将审计日志记录放在应用程序控制器中,我将无法确保记录所有CRUD操作(例如,调用Subject.create的Case模型中的代码不会记录)。我也认为我会失去状态变化。
有没有办法确保在整个关联树中记录所有CRUD操作,以便记录登录用户的用户ID?
答案 0 :(得分:0)
可以使用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
。
关于操作的校验和?您可以覆盖inspect以一致的方式打印包含记录中所有信息的字符串,然后为其生成校验和。当你在它的时候,不妨把它作为写入日志方法的一部分添加到审计日志中。
将每个访问日志写为具有确定名称("/logs/audits/#{class}/#{id}/#{timestamp}"
)的单独文件,并在保存后删除写入权限。 File.chmod(0555, access_log_file)
关于第4项要求。如果您在任何嵌套关系上使用accepts_nested_attributes_for,那将自动进入我的第一个解决方案。并且:autosave =>对于belongs_to关系,则为true。
如果要将校验和保存到审核日志中,则可以将检查信息转入before_save方法,以确保您正在处理的对象未被篡改。只需检查对象的最新审核日志并匹配校验和即可。