#9 Active Storage - Checksum removed from the revision

This commit is contained in:
Karel Pičman 2025-11-28 13:35:20 +01:00
parent 9a4b9a5da3
commit deb63e2b03
14 changed files with 47 additions and 67 deletions

View File

@ -141,7 +141,6 @@ class DmsfFilesController < ApplicationController
revision.size = upload.size revision.size = upload.size
revision.disk_filename = revision.new_storage_filename revision.disk_filename = revision.new_storage_filename
revision.mime_type = upload.mime_type revision.mime_type = upload.mime_type
revision.digest = upload.digest
revision.file.attach( revision.file.attach(
io: File.open(upload.tempfile_path), io: File.open(upload.tempfile_path),
filename: revision.disk_filename, filename: revision.disk_filename,
@ -153,7 +152,6 @@ class DmsfFilesController < ApplicationController
revision.size = last_revision.size revision.size = last_revision.size
revision.disk_filename = last_revision.disk_filename revision.disk_filename = last_revision.disk_filename
revision.mime_type = last_revision.mime_type revision.mime_type = last_revision.mime_type
revision.digest = last_revision.digest
end end
# Custom fields # Custom fields
revision.copy_custom_field_values(params[:dmsf_file_revision][:custom_field_values], last_revision) revision.copy_custom_field_values(params[:dmsf_file_revision][:custom_field_values], last_revision)

View File

@ -49,7 +49,6 @@ class DmsfUploadController < ApplicationController
@uploads.push upload @uploads.push upload
params[:committed_files][key][:disk_filename] = upload.disk_filename params[:committed_files][key][:disk_filename] = upload.disk_filename
params[:committed_files][key][:digest] = upload.digest
params[:committed_files][key][:tempfile_path] = upload.tempfile_path params[:committed_files][key][:tempfile_path] = upload.tempfile_path
end end
commit_files if params[:committed_files].present? commit_files if params[:committed_files].present?

View File

@ -70,7 +70,6 @@ module DmsfUploadHelper
end end
new_revision.mime_type = committed_file[:mime_type] new_revision.mime_type = committed_file[:mime_type]
new_revision.size = committed_file[:size] new_revision.size = committed_file[:size]
new_revision.digest = committed_file[:digest]
# Custom fields # Custom fields
new_revision.copy_custom_field_values(committed_file[:custom_field_values]) new_revision.copy_custom_field_values(committed_file[:custom_field_values])
# Need to save file first to generate id for it in case of creation. # Need to save file first to generate id for it in case of creation.

View File

@ -114,6 +114,10 @@ class DmsfFileRevision < ApplicationRecord
shared_file shared_file
end end
def checksum
file.blob.checksum
end
def visible?(_user = nil) def visible?(_user = nil)
deleted == STATUS_ACTIVE deleted == STATUS_ACTIVE
end end
@ -237,7 +241,6 @@ class DmsfFileRevision < ApplicationRecord
new_revision.source_revision = self new_revision.source_revision = self
new_revision.user = User.current new_revision.user = User.current
new_revision.name = name new_revision.name = name
new_revision.digest = digest
new_revision new_revision
end end
@ -322,7 +325,6 @@ class DmsfFileRevision < ApplicationRecord
content_type: mime_type, content_type: mime_type,
identify: false identify: false
) )
self.digest = file.blob.checksum
end end
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields # Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
@ -360,20 +362,6 @@ class DmsfFileRevision < ApplicationRecord
format2 format2
end end
def create_digest
self.digest = Digest::SHA256.file(path).hexdigest
rescue StandardError => e
Rails.logger.error e.message
self.digest = 0
end
# Returns either MD5 or SHA256 depending on the way self.digest was computed
def digest_type
return nil if digest.blank?
digest.size < 64 ? 'MD5' : 'SHA256'
end
def tooltip def tooltip
text = description.presence || +'' text = description.presence || +''
if comment.present? if comment.present?

View File

@ -20,7 +20,7 @@
# Upload # Upload
class DmsfUpload class DmsfUpload
attr_accessor :name, :disk_filename, :mime_type, :title, :description, :comment, :major_version, :minor_version, attr_accessor :name, :disk_filename, :mime_type, :title, :description, :comment, :major_version, :minor_version,
:patch_version, :locked, :workflow, :custom_values, :tempfile_path, :digest, :token :patch_version, :locked, :workflow, :custom_values, :tempfile_path, :token
attr_reader :size attr_reader :size
def disk_file def disk_file
@ -36,8 +36,7 @@ class DmsfUpload
original_filename: a.filename, original_filename: a.filename,
comment: uploaded_file[:description], comment: uploaded_file[:description],
tempfile_path: a.diskfile, tempfile_path: a.diskfile,
token: uploaded_file[:token], token: uploaded_file[:token]
digest: a.digest
} }
DmsfUpload.new project, folder, uploaded DmsfUpload.new project, folder, uploaded
else else

View File

@ -135,10 +135,10 @@
<%= content_tag :div, l(:label_mime), class: 'label' %> <%= content_tag :div, l(:label_mime), class: 'label' %>
<%= content_tag :div, revision.mime_type, class: 'value' %> <%= content_tag :div, revision.mime_type, class: 'value' %>
</div> </div>
<% if revision.digest.present? %> <% if revision.checksum.present? %>
<div class="status attribute"> <div class="status attribute">
<%= content_tag :div, l(:field_digest), class: 'label' %> <%= content_tag :div, l(:field_digest), class: 'label' %>
<%= content_tag :div, "#{revision.digest_type}: #{revision.digest}", class: 'value wiki' %> <%= content_tag :div, revision.checksum, class: 'value wiki' %>
</div> </div>
<% end %> <% end %>
<%= render 'dmsf/custom_fields', object: revision %> <%= render 'dmsf/custom_fields', object: revision %>

View File

@ -20,7 +20,6 @@
<div class="box tabular dmfs-box-tabular"> <div class="box tabular dmfs-box-tabular">
<%= hidden_field_tag "committed_files[#{i}][disk_filename]", upload.disk_filename %> <%= hidden_field_tag "committed_files[#{i}][disk_filename]", upload.disk_filename %>
<%= hidden_field_tag "committed_files[#{i}][token]", upload.token %> <%= hidden_field_tag "committed_files[#{i}][token]", upload.token %>
<%= hidden_field_tag "committed_files[#{i}][digest]", upload.digest %>
<%= hidden_field_tag "committed_files[#{i}][size]", upload.size %> <%= hidden_field_tag "committed_files[#{i}][size]", upload.size %>
<div class="splitcontent"> <div class="splitcontent">
<div class="splitcontentleft"> <div class="splitcontentleft">

View File

@ -22,6 +22,5 @@
"content_type": "<%= @tempfile.content_type.gsub('"', '').html_safe %>", "content_type": "<%= @tempfile.content_type.gsub('"', '').html_safe %>",
"disk_filename": "<%= @disk_filename.html_safe %>", "disk_filename": "<%= @disk_filename.html_safe %>",
"tempfile_path": "<%= @tempfile_path.html_safe %>", "tempfile_path": "<%= @tempfile_path.html_safe %>",
"digest": "<%= @digest.html_safe %>",
"token": "<%= @token.html_safe %>" "token": "<%= @token.html_safe %>"
} }

View File

@ -22,4 +22,8 @@ class AddDigestToRevision < ActiveRecord::Migration[4.2]
def up def up
add_column :dmsf_file_revisions, :digest, :string, limit: 40, default: '', null: false add_column :dmsf_file_revisions, :digest, :string, limit: 40, default: '', null: false
end end
def down
remove_column :dmsf_file_revisions, :digest
end
end end

View File

@ -25,7 +25,7 @@ class ChangeRevisionDigestLimitTo64 < ActiveRecord::Migration[4.2]
def down def down
# Mysql2::Error: Data too long for column 'digest' # Mysql2::Error: Data too long for column 'digest'
# Recalculation of checksums for all revisions is technically possible but costs are to high. # Recalculation of checksums for all revisions is technically possible but costs are too high.
# change_column :dmsf_file_revisions, :digest, :string, limit: 40 # change_column :dmsf_file_revisions, :digest, :string, limit: 40
end end
end end

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
# Redmine plugin for Document Management System "Features"
#
# Karel Pičman <karel.picman@kontron.com>
#
# This file is part of Redmine DMSF plugin.
#
# Redmine DMSF plugin is free software: you can redistribute it and/or modify it under the terms of the GNU General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Redmine DMSF plugin is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with Redmine DMSF plugin. If not, see
# <https://www.gnu.org/licenses/>.
# Add column
class RemoveDigestFromRevision < ActiveRecord::Migration[7.0]
def up
remove_column :dmsf_file_revisions, :digest
end
def down
add_column :dmsf_file_revisions, :digest, :string, limit: 64, default: '', null: false
# Recalculation of checksums for all revisions is technically possible but costs are too high.
end
end

View File

@ -174,7 +174,6 @@ module RedmineDmsf
uploaded_file[:size] = upload.size uploaded_file[:size] = upload.size
uploaded_file[:mime_type] = upload.mime_type uploaded_file[:mime_type] = upload.mime_type
uploaded_file[:tempfile_path] = upload.tempfile_path uploaded_file[:tempfile_path] = upload.tempfile_path
uploaded_file[:digest] = upload.digest
if params[:dmsf_attachments_wfs].present? && params[:dmsf_attachments_wfs][key].present? if params[:dmsf_attachments_wfs].present? && params[:dmsf_attachments_wfs][key].present?
uploaded_file[:workflow_id] = params[:dmsf_attachments_wfs][key].to_i uploaded_file[:workflow_id] = params[:dmsf_attachments_wfs][key].to_i
end end

View File

@ -18,7 +18,6 @@ dmsf_file_revisions_001:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: 1 dmsf_workflow_assigned_by_user_id: 1
dmsf_workflow_started_by_user_id: 1 dmsf_workflow_started_by_user_id: 1
digest: '202cb962ac59075b964b07152d234b70'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
#revision for file on non-enabled project #revision for file on non-enabled project
@ -41,7 +40,6 @@ dmsf_file_revisions_002:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: NULL dmsf_workflow_assigned_by_user_id: NULL
dmsf_workflow_started_by_user_id: NULL dmsf_workflow_started_by_user_id: NULL
digest: '202cb962ac59075b964b07152d234b70'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
#revision for deleted file on dmsf-enabled project #revision for deleted file on dmsf-enabled project
@ -64,7 +62,6 @@ dmsf_file_revisions_003:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: NULL dmsf_workflow_assigned_by_user_id: NULL
dmsf_workflow_started_by_user_id: NULL dmsf_workflow_started_by_user_id: NULL
digest: '202cb962ac59075b964b07152d234b70'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
dmsf_file_revisions_004: dmsf_file_revisions_004:
@ -86,30 +83,7 @@ dmsf_file_revisions_004:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: NULL dmsf_workflow_assigned_by_user_id: NULL
dmsf_workflow_started_by_user_id: NULL dmsf_workflow_started_by_user_id: NULL
digest: '202cb962ac59075b964b07152d234b70'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
#dmsf_file_revisions_005:
# id: 5
# dmsf_file_id: 1
# source_dmsf_file_revision_id: NULL
# name: 'test5.txt'
# disk_filename: 'test5.txt'
# size: 4
# mime_type: 'application/vnd.oasis.opendocument.text'
# title: 'Test file'
# description: NULL
# workflow: 1 # DmsfWorkflow::STATE_WAITING_FOR_APPROVAL
# minor_version: 1
# major_version: 1
# comment: 'Wrong mime type in order to have Edit content menu item'
# deleted: 0
# deleted_by_user_id: NULL
# user_id: 1
# dmsf_workflow_assigned_by_user_id: NULL
# dmsf_workflow_started_by_user_id: NULL
# digest: '81dc9bdb52d04dc20036dbd8313ed055'
# created_at: 2017-04-18 14:52:28 +02:00
dmsf_file_revisions_006: dmsf_file_revisions_006:
id: 6 id: 6
@ -130,7 +104,6 @@ dmsf_file_revisions_006:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: NULL dmsf_workflow_assigned_by_user_id: NULL
dmsf_workflow_started_by_user_id: NULL dmsf_workflow_started_by_user_id: NULL
digest: '8ae50031bb862c4a69f2bab5cd1f2051'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
dmsf_file_revisions_007: dmsf_file_revisions_007:
@ -152,7 +125,6 @@ dmsf_file_revisions_007:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: NULL dmsf_workflow_assigned_by_user_id: NULL
dmsf_workflow_started_by_user_id: NULL dmsf_workflow_started_by_user_id: NULL
digest: '5376a8cee7e15c8aa1023d27f3209720'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
dmsf_file_revisions_008: dmsf_file_revisions_008:
@ -195,7 +167,6 @@ dmsf_file_revisions_009:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: NULL dmsf_workflow_assigned_by_user_id: NULL
dmsf_workflow_started_by_user_id: NULL dmsf_workflow_started_by_user_id: NULL
digest: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
dmsf_file_revisions_010: dmsf_file_revisions_010:
@ -217,7 +188,6 @@ dmsf_file_revisions_010:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: 1 dmsf_workflow_assigned_by_user_id: 1
dmsf_workflow_started_by_user_id: 1 dmsf_workflow_started_by_user_id: 1
digest: '81dc9bdb52d04dc20036dbd8313ed055'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
dmsf_file_revisions_011: dmsf_file_revisions_011:
@ -239,7 +209,6 @@ dmsf_file_revisions_011:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: 1 dmsf_workflow_assigned_by_user_id: 1
dmsf_workflow_started_by_user_id: 1 dmsf_workflow_started_by_user_id: 1
digest: '81dc9bdb52d04dc20036dbd8313ed055'
created_at: 2017-04-18 14:52:27 +02:00 created_at: 2017-04-18 14:52:27 +02:00
dmsf_file_revisions_012: dmsf_file_revisions_012:
@ -261,7 +230,6 @@ dmsf_file_revisions_012:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: NULL dmsf_workflow_assigned_by_user_id: NULL
dmsf_workflow_started_by_user_id: NULL dmsf_workflow_started_by_user_id: NULL
digest: '81dc9bdb52d04dc20036dbd8313ed055'
created_at: 2022-02-03 13:39:27 +02:00 created_at: 2022-02-03 13:39:27 +02:00
dmsf_file_revisions_013: dmsf_file_revisions_013:
@ -283,5 +251,4 @@ dmsf_file_revisions_013:
user_id: 1 user_id: 1
dmsf_workflow_assigned_by_user_id: NULL dmsf_workflow_assigned_by_user_id: NULL
dmsf_workflow_started_by_user_id: NULL dmsf_workflow_started_by_user_id: NULL
digest: '89a6d0ea9aafc21a978152f3e4977812d5d7d623505749471f256a90fc7c5f72'
created_at: 2017-04-01 08:54:00 +02:00 created_at: 2017-04-01 08:54:00 +02:00

View File

@ -70,11 +70,6 @@ class DmsfFileRevisionTest < RedmineDmsf::Test::UnitTest
assert_nil DmsfFileRevision.find_by(id: @revision13.id) assert_nil DmsfFileRevision.find_by(id: @revision13.id)
end end
def test_digest_type
# Old type MD5
assert_equal 'MD5', @revision1.digest_type
end
def test_new_storage_filename def test_new_storage_filename
# Create a file. # Create a file.
f = DmsfFile.new f = DmsfFile.new
@ -337,4 +332,8 @@ class DmsfFileRevisionTest < RedmineDmsf::Test::UnitTest
assert_nil @revision2.dmsf_workflow_started_by_user_id assert_nil @revision2.dmsf_workflow_started_by_user_id
assert_nil @revision2.dmsf_workflow_started_at assert_nil @revision2.dmsf_workflow_started_at
end end
def test_checksum
assert_equal @revision1.checksum, @revision1.file.blob.checksum
end
end end