Class: ForestAdminAgent::AuditTrail::ActionCapture
- Inherits:
-
Object
- Object
- ForestAdminAgent::AuditTrail::ActionCapture
- Includes:
- Recording
- Defined in:
- lib/forest_admin_agent/audit_trail/action_capture.rb
Overview
Records smart-action runs into the same table as the field-level history: the submitted form on the
previous_values side, what the action answered on the new_values side.
Capture cannot see them — the customizer has no Execute hook — and an action's writes are only
audited when they go through the Forest data layer, so a direct ORM write stays invisible. What lands
here is the run itself: who ran which action, on which records, with which form, and how it ended.
Same protocol as a write: #pending before the action, #confirm after. The route owns the gate, so a
pending insert that fails refuses the run under critical: true.
Constant Summary collapse
- EXECUTED =
'action'.freeze
- FAILED =
'action_failed'.freeze
- NO_RECORD =
A global action, and a bulk run over a selection wider than the cap, name no single target: they get one row attached to no record rather than none at all.
''.freeze
- RESULT_FIELDS =
What of the action's answer is worth keeping — an allowlist, not a denylist: a result also carries the file's contents, a webhook's body and headers and arbitrary response headers. File bytes have no business in an audit table and the other two routinely hold credentials, and an allowlist means a field added to a result later is not stored until someone decides it should be.
htmlis left out too: operator-facing markup, sometimes large, and the message already says what happened. %i[type message name mime_type method url path].freeze
- URL_FIELDS =
Either can carry userinfo credentials or a signed one-time token, which would then sit permanently in the one table nobody deletes from.
%i[url path].freeze
Constants included from Recording
Recording::DONE, Recording::IDENTITY, Recording::PENDING, Recording::REDACTED
Instance Method Summary collapse
-
#confirm(ids, result: nil, failed: false) ⇒ Object
Best-effort: the action has already run, so a failure here loses the answer, never the run.
-
#initialize(store, redact = {}) ⇒ ActionCapture
constructor
A new instance of ActionCapture.
-
#pending(caller:, collection:, action_name:, form_values:, record_ids:) ⇒ Object
One row per targeted record, provisionally an
action— #confirm settles which it really was.
Methods included from Recording
#audit_safely, #correlation_key_for, #identity_of, #now, #redact
Constructor Details
#initialize(store, redact = {}) ⇒ ActionCapture
Returns a new instance of ActionCapture.
32 33 34 35 |
# File 'lib/forest_admin_agent/audit_trail/action_capture.rb', line 32 def initialize(store, redact = {}) @store = store @redact = redact || {} end |
Instance Method Details
#confirm(ids, result: nil, failed: false) ⇒ Object
Best-effort: the action has already run, so a failure here loses the answer, never the run.
60 61 62 63 64 65 66 67 68 |
# File 'lib/forest_admin_agent/audit_trail/action_capture.rb', line 60 def confirm(ids, result: nil, failed: false) return if ids.nil? || ids.empty? audit_safely do answer = summarize(result) ids.each { |id| @store.confirm(id, operation: failed ? FAILED : EXECUTED, new_values: answer) } end end |
#pending(caller:, collection:, action_name:, form_values:, record_ids:) ⇒ Object
One row per targeted record, provisionally an action — #confirm settles which it really was. Returns
the row ids to confirm.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/forest_admin_agent/audit_trail/action_capture.rb', line 39 def pending(caller:, collection:, action_name:, form_values:, record_ids:) return [] unless @store = now correlation_key = correlation_key_for(caller) identity = identity_of(caller) submitted = redact(form_values || {}, @redact[collection] || []) ids = record_ids.empty? ? [NO_RECORD] : record_ids @store.append_all( ids.map do |record_id| AuditRecord.new( timestamp: , operation: EXECUTED, collection: collection, record_id: record_id, status: PENDING, action_name: action_name, correlation_key: correlation_key, previous_values: submitted, new_values: {}, **identity ) end ) end |