Module: AuditLog

Defined in:
lib/generators/ruby_cms/templates/services/audit_log.rb

Overview

AuditLog.record(actor:, action:, target:, summary:, request:, meta: {})

Persists an AuditLogEntry. Never raises — audit failures must not break the user-facing action. Errors are logged at warn level.

Class Method Summary collapse

Class Method Details

.actor_email(actor) ⇒ Object



28
29
30
31
32
33
# File 'lib/generators/ruby_cms/templates/services/audit_log.rb', line 28

def actor_email(actor)
  return "system"  if actor == :system
  return "unknown" if actor.nil?

  actor.respond_to?(:email_address) ? actor.email_address : actor.to_s
end

.record(action:, actor: nil, target: nil, summary: nil, request: nil, meta: {}) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/generators/ruby_cms/templates/services/audit_log.rb', line 10

def record(action:, actor: nil, target: nil, summary: nil, request: nil, meta: {})
  AuditLogEntry.create!(
    actor_email: actor_email(actor),
    actor_id: actor.respond_to?(:id) ? actor.id : nil,
    action: action.to_s,
    target_type: target_type(target),
    target_id: target_id(target),
    target_label: target_label(target),
    summary: summary&.to_s&.truncate(500),
    ip: request&.remote_ip,
    user_agent: request&.user_agent&.truncate(500),
    metadata: meta || {}
  )
rescue StandardError => e
  Rails.logger.warn("[AuditLog] failed to record action=#{action}: #{e.class}: #{e.message}")
  nil
end

.target_id(target) ⇒ Object



42
43
44
45
46
# File 'lib/generators/ruby_cms/templates/services/audit_log.rb', line 42

def target_id(target)
  return nil unless target.respond_to?(:id)

  target.id
end

.target_label(target) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/generators/ruby_cms/templates/services/audit_log.rb', line 48

def target_label(target)
  return target if target.kind_of?(String)
  return nil    if target.nil?

  %i[title name email_address email slug key to_s].each do |m|
    next unless target.respond_to?(m)

    val = target.public_send(m)
    return val.to_s.truncate(200) if val.present?
  end
  "#{target.class.name}##{target.id}"
end

.target_type(target) ⇒ Object



35
36
37
38
39
40
# File 'lib/generators/ruby_cms/templates/services/audit_log.rb', line 35

def target_type(target)
  return nil if target.nil?
  return target if target.kind_of?(String)

  target.class.name
end