Class: Textus::Dispatch::Middleware::AuditIndex

Inherits:
Base
  • Object
show all
Defined in:
lib/textus/dispatch/middleware/audit_index.rb

Overview

Shadows successful write operations into the SQLite audit_events table synchronously after dispatch, without the command knowing. Read verbs and failed writes pass through unchanged.

Constant Summary collapse

INDEXED_CONTRACTS =
[
  Contracts::PutEntry,
  Contracts::DeleteKey,
  Contracts::MoveKey,
].freeze

Instance Method Summary collapse

Methods inherited from Base

inherited, middleware_name

Constructor Details

#initialize(job_store:, audit_log:) ⇒ AuditIndex

Returns a new instance of AuditIndex.



18
19
20
21
22
# File 'lib/textus/dispatch/middleware/audit_index.rb', line 18

def initialize(job_store:, audit_log:)
  super()
  @job_store = job_store
  @audit_log = audit_log
end

Instance Method Details

#call(container:, command:, call:, next_handler:) ⇒ Object

rubocop:disable Lint/UnusedMethodArgument



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/textus/dispatch/middleware/audit_index.rb', line 24

def call(container:, command:, call:, next_handler:) # rubocop:disable Lint/UnusedMethodArgument
  result = next_handler.call(command, call)
  return result unless result.success? && INDEXED_CONTRACTS.include?(command.class)

  key = command.respond_to?(:key) ? command.key : nil
  return result unless key

  seq = @audit_log.latest_seq
  verb = command.class.name.split("::").last
                .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
                .gsub(/([a-z\d])([A-Z])/, '\1_\2')
                .downcase

  @job_store.insert_audit_event(
    seq: seq,
    ts: Time.now.utc.iso8601,
    role: call.role,
    verb: verb,
    key: key,
    etag_before: nil,
    etag_after: result.value.is_a?(Hash) ? result.value["etag"] : nil,
  )
  result
end