diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-23 12:24:52 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-23 12:24:52 +0200 |
| commit | 932d4a4be40587fa6d489eca16a1ef6d6f2936d1 (patch) | |
| tree | a7512889db54347845ce8f72e5a2155d917b4500 /app | |
| parent | 6ef98ad444631b1d5ba67bb16aaaa2afdfa53ae0 (diff) | |
Witness asset uploads and out-of-band attaches in the action log
Diffstat (limited to 'app')
| -rw-r--r-- | app/controllers/assets_controller.rb | 5 | ||||
| -rw-r--r-- | app/helpers/node_actions_helper.rb | 15 | ||||
| -rw-r--r-- | app/models/node.rb | 8 | ||||
| -rw-r--r-- | app/models/node_action.rb | 11 |
4 files changed, 39 insertions, 0 deletions
diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index 8df4c94d..7edd9c05 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb | |||
| @@ -50,6 +50,11 @@ class AssetsController < ApplicationController | |||
| 50 | respond_to do |format| | 50 | respond_to do |format| |
| 51 | if @asset.save | 51 | if @asset.save |
| 52 | flash[:notice] = 'Asset was successfully created.' | 52 | flash[:notice] = 'Asset was successfully created.' |
| 53 | NodeAction.record!(:participants => [@asset], :user => current_user, | ||
| 54 | :action => "asset_create", | ||
| 55 | :asset_name => @asset.name, | ||
| 56 | :content_type => @asset.upload_content_type, | ||
| 57 | :path => @asset.upload.url.sub(/\?\d+$/, "")) | ||
| 53 | attach_to(attach_node) if attach_node | 58 | attach_to(attach_node) if attach_node |
| 54 | format.html { redirect_to(@asset) } | 59 | format.html { redirect_to(@asset) } |
| 55 | format.xml { render :xml => @asset, :status => :created, :location => @asset } | 60 | format.xml { render :xml => @asset, :status => :created, :location => @asset } |
diff --git a/app/helpers/node_actions_helper.rb b/app/helpers/node_actions_helper.rb index 02d1ba83..ed8d0407 100644 --- a/app/helpers/node_actions_helper.rb +++ b/app/helpers/node_actions_helper.rb | |||
| @@ -13,6 +13,9 @@ module NodeActionsHelper | |||
| 13 | "destroy" => "trash-x", | 13 | "destroy" => "trash-x", |
| 14 | "discard_autosave" => "eraser", | 14 | "discard_autosave" => "eraser", |
| 15 | "destroy_draft" => "eraser", | 15 | "destroy_draft" => "eraser", |
| 16 | "asset_create" => "upload", | ||
| 17 | "asset_attach" => "paperclip", | ||
| 18 | "asset_destroy" => "file-x" | ||
| 16 | }.freeze | 19 | }.freeze |
| 17 | 20 | ||
| 18 | def verb_icon action | 21 | def verb_icon action |
| @@ -181,6 +184,18 @@ module NodeActionsHelper | |||
| 181 | :path => h(action.metadata["path"])).html_safe | 184 | :path => h(action.metadata["path"])).html_safe |
| 182 | end | 185 | end |
| 183 | 186 | ||
| 187 | def summarize_asset_create action | ||
| 188 | t("node_actions.asset_create", :actor => actor_ref(action), | ||
| 189 | :asset => h(action.metadata["asset_name"].presence || action.metadata["path"])).html_safe | ||
| 190 | end | ||
| 191 | |||
| 192 | def summarize_asset_attach action | ||
| 193 | m = action.metadata | ||
| 194 | key = m["headline"] ? "node_actions.asset_attach_headline" : "node_actions.asset_attach" | ||
| 195 | t(key, :actor => actor_ref(action), :subject => subject_ref(action), | ||
| 196 | :asset => h(m["asset_name"].presence || m["path"])).html_safe | ||
| 197 | end | ||
| 198 | |||
| 184 | def summarize_asset_destroy action | 199 | def summarize_asset_destroy action |
| 185 | m = action.metadata | 200 | m = action.metadata |
| 186 | parts = [t("node_actions.asset_destroy", :actor => actor_ref(action), | 201 | parts = [t("node_actions.asset_destroy", :actor => actor_ref(action), |
diff --git a/app/models/node.rb b/app/models/node.rb index 7a93e799..0a9cd2d1 100644 --- a/app/models/node.rb +++ b/app/models/node.rb | |||
| @@ -501,6 +501,14 @@ class Node < ApplicationRecord | |||
| 501 | to_attach.each do |row| | 501 | to_attach.each do |row| |
| 502 | row.related_assets.create!(:asset => asset, :headline => headline_state == :set) | 502 | row.related_assets.create!(:asset => asset, :headline => headline_state == :set) |
| 503 | end | 503 | end |
| 504 | |||
| 505 | if to_attach.any? | ||
| 506 | metadata = { :asset_name => asset.name, | ||
| 507 | :path => asset.upload.url.sub(/\?\d+$/, "") } | ||
| 508 | metadata[:headline] = true if headline_state == :set | ||
| 509 | NodeAction.record!(:node => self, :participants => [self, asset], | ||
| 510 | :user => user, :action => "asset_attach", **metadata) | ||
| 511 | end | ||
| 504 | end | 512 | end |
| 505 | 513 | ||
| 506 | { :attached => to_attach.size, | 514 | { :attached => to_attach.size, |
diff --git a/app/models/node_action.rb b/app/models/node_action.rb index 9ed0b628..aa52f489 100644 --- a/app/models/node_action.rb +++ b/app/models/node_action.rb | |||
| @@ -69,6 +69,17 @@ class NodeAction < ApplicationRecord | |||
| 69 | # "path" -- final path, flat string (create-symmetric) | 69 | # "path" -- final path, flat string (create-symmetric) |
| 70 | # "destroyed_descendants" -- integer, only when positive; one entry | 70 | # "destroyed_descendants" -- integer, only when positive; one entry |
| 71 | # at the root, per the subtree rule. | 71 | # at the root, per the subtree rule. |
| 72 | # | ||
| 73 | # "asset_create" (witnessed upload; participants: the asset alone): | ||
| 74 | # "asset_name", "content_type", "path" -- flat strings | ||
| 75 | # | ||
| 76 | # "asset_attach" (out-of-band attach via Node#attach_asset!; written | ||
| 77 | # only when at least one new join was created, per the tandem rule -- | ||
| 78 | # in-editor curation stays draft-scoped and surfaces at publish. | ||
| 79 | # participants: the node (primary) and the asset): | ||
| 80 | # "asset_name", "path" -- flat strings | ||
| 81 | # "headline" -- boolean, only when set by this attach | ||
| 82 | # | ||
| 72 | # "asset_destroy" (witnessed asset deletion; always written, even for | 83 | # "asset_destroy" (witnessed asset deletion; always written, even for |
| 73 | # unattached assets -- the files were publicly reachable; node column | 84 | # unattached assets -- the files were publicly reachable; node column |
| 74 | # nil, subjects via participants: the asset plus every then-attached | 85 | # nil, subjects via participants: the asset plus every then-attached |
