summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/assets_controller.rb2
-rw-r--r--app/helpers/node_actions_helper.rb11
-rw-r--r--app/models/asset.rb30
-rw-r--r--app/models/node_action.rb9
4 files changed, 51 insertions, 1 deletions
diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb
index fbede0a7..8df4c94d 100644
--- a/app/controllers/assets_controller.rb
+++ b/app/controllers/assets_controller.rb
@@ -81,7 +81,7 @@ class AssetsController < ApplicationController
81 # DELETE /assets/1.xml 81 # DELETE /assets/1.xml
82 def destroy 82 def destroy
83 @asset = Asset.find(params[:id]) 83 @asset = Asset.find(params[:id])
84 @asset.destroy 84 @asset.destroy_witnessed!(:user => current_user)
85 85
86 respond_to do |format| 86 respond_to do |format|
87 format.html { redirect_to(assets_url) } 87 format.html { redirect_to(assets_url) }
diff --git a/app/helpers/node_actions_helper.rb b/app/helpers/node_actions_helper.rb
index fd8cc36e..02d1ba83 100644
--- a/app/helpers/node_actions_helper.rb
+++ b/app/helpers/node_actions_helper.rb
@@ -180,4 +180,15 @@ module NodeActionsHelper
180 t("node_actions.destroy", :actor => actor_ref(action), :subject => subject_ref(action), 180 t("node_actions.destroy", :actor => actor_ref(action), :subject => subject_ref(action),
181 :path => h(action.metadata["path"])).html_safe 181 :path => h(action.metadata["path"])).html_safe
182 end 182 end
183
184 def summarize_asset_destroy action
185 m = action.metadata
186 parts = [t("node_actions.asset_destroy", :actor => actor_ref(action),
187 :asset => h(m["asset_name"].presence || m["path"]))]
188 parts << t("node_actions.asset_destroy_detached",
189 :paths => h(Array(m["detached_from"]).join(", "))) if m["detached_from"].present?
190 parts << t("node_actions.asset_destroy_headlines",
191 :paths => h(Array(m["headline_removed_from"]).join(", "))) if m["headline_removed_from"].present?
192 safe_join(parts, " ")
193 end
183end 194end
diff --git a/app/models/asset.rb b/app/models/asset.rb
index 73970e21..8cec4371 100644
--- a/app/models/asset.rb
+++ b/app/models/asset.rb
@@ -40,4 +40,34 @@ class Asset < ApplicationRecord
40 Node.where("head_id IN (:ids) OR draft_id IN (:ids) OR autosave_id IN (:ids)", 40 Node.where("head_id IN (:ids) OR draft_id IN (:ids) OR autosave_id IN (:ids)",
41 :ids => page_ids).distinct 41 :ids => page_ids).distinct
42 end 42 end
43
44 # Witnessed destruction. Destroying an asset is a public-facing act
45 # even when unattached. The original and its variants are publicly
46 # reachable under /system/uploads, so an entry is always written,
47 # before the row and its files die. Every currently-attached node
48 # participates so its zoomed history shows the loss; the asset itself
49 # participates as the first non-Node subject (its participant row
50 # dangles after destroy, by design, the name lives on in metadata).
51 def destroy_witnessed! user:
52 ActiveRecord::Base.transaction do
53 affected = attached_nodes.to_a
54 headline_losses = affected.select do |node|
55 [node.head, node.draft, node.autosave].compact.any? do |row|
56 row.related_assets.exists?(:asset_id => id, :headline => true)
57 end
58 end
59
60 metadata = {
61 :asset_name => name,
62 :content_type => upload_content_type,
63 :path => upload.url.sub(/\?\d+$/, ""),
64 }
65 metadata[:detached_from] = affected.map(&:unique_name) if affected.any?
66 metadata[:headline_removed_from] = headline_losses.map(&:unique_name) if headline_losses.any?
67
68 NodeAction.record!(:participants => [self] + affected, :user => user,
69 :action => "asset_destroy", **metadata)
70 destroy!
71 end
72 end
43end 73end
diff --git a/app/models/node_action.rb b/app/models/node_action.rb
index 8a3dd8b7..9ed0b628 100644
--- a/app/models/node_action.rb
+++ b/app/models/node_action.rb
@@ -69,6 +69,15 @@ 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 # "asset_destroy" (witnessed asset deletion; always written, even for
73 # unattached assets -- the files were publicly reachable; node column
74 # nil, subjects via participants: the asset plus every then-attached
75 # node):
76 # "asset_name" -- flat string
77 # "content_type" -- flat string
78 # "path" -- public original path, flat string
79 # "detached_from" -- array of unique_names, only when any
80 # "headline_removed_from" -- array of unique_names, only when any
72 # 81 #
73 # Reserved: "demote" (via "trash" | "depublish") for an explicit 82 # Reserved: "demote" (via "trash" | "depublish") for an explicit
74 # depublish workflow, if ever built. 83 # depublish workflow, if ever built.