From 52f245e913490498fdfcbe077d641176cb4389ed Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Fri, 22 Apr 2016 12:46:30 +0200 Subject: [PATCH] Add MD5 of each revision in the detail view of documents #527 --- app/controllers/dmsf_files_controller.rb | 6 ++ app/controllers/dmsf_upload_controller.rb | 1 + app/helpers/dmsf_helper.rb | 11 --- app/models/dmsf_file_revision.rb | 22 +++++ .../dmsf_files/_revision_access.html.erb | 20 ++--- app/views/dmsf_files/show.html.erb | 80 +++++++++---------- .../20160421150501_add_digest_to_revision.rb | 29 +++++++ lib/tasks/dmsf_create_digests.rake | 63 +++++++++++++++ 8 files changed, 170 insertions(+), 62 deletions(-) create mode 100644 db/migrate/20160421150501_add_digest_to_revision.rb create mode 100644 lib/tasks/dmsf_create_digests.rake diff --git a/app/controllers/dmsf_files_controller.rb b/app/controllers/dmsf_files_controller.rb index c67b988e..441bc5bf 100644 --- a/app/controllers/dmsf_files_controller.rb +++ b/app/controllers/dmsf_files_controller.rb @@ -139,10 +139,16 @@ class DmsfFilesController < ApplicationController revision.size = last_revision.size revision.disk_filename = last_revision.disk_filename revision.mime_type = last_revision.mime_type + if last_revision.digest.blank? + revision.digest = DmsfFileRevision.create_digest last_revision.disk_file + else + revision.digest = last_revision.digest + end else revision.size = file_upload.size revision.disk_filename = revision.new_storage_filename revision.mime_type = Redmine::MimeType.of(file_upload.original_filename) + revision.digest = DmsfFileRevision.create_digest file_upload.path end # Custom fields diff --git a/app/controllers/dmsf_upload_controller.rb b/app/controllers/dmsf_upload_controller.rb index 290c65f0..fdfc835c 100644 --- a/app/controllers/dmsf_upload_controller.rb +++ b/app/controllers/dmsf_upload_controller.rb @@ -187,6 +187,7 @@ class DmsfUploadController < ApplicationController end new_revision.mime_type = Redmine::MimeType.of(new_revision.name) new_revision.size = File.size(commited_disk_filepath) + new_revision.digest = DmsfFileRevision.create_digest commited_disk_filepath # Need to save file first to generate id for it in case of creation. # File id is needed to properly generate revision disk filename diff --git a/app/helpers/dmsf_helper.rb b/app/helpers/dmsf_helper.rb index 893a6a1a..a5f33c6c 100644 --- a/app/helpers/dmsf_helper.rb +++ b/app/helpers/dmsf_helper.rb @@ -67,17 +67,6 @@ module DmsfHelper return "#{Redmine::Utils.relative_url_root}/plugin_assets/#{plugin}/#{asset_type}/#{source}" end - def self.to_time(obj) - #Right, enough of bugs, let's try a better approach here. - return unless obj - return obj.to_time(ActiveRecord::Base.default_timezone) if obj.is_a?(String) - - # Why can't Mysql::Time conform to time object? - without a utc? method it breaks redmine's - # rendering method, so we convert it to string, and back into time - not the most efficient - # of methods - however seems functional. Not sure if MySQL - (obj.class.name == 'Mysql::Time') ? obj.to_s.to_time(ActiveRecord::Base.default_timezone) : obj - end - def self.dmsf_tree(parent, obj, tree = nil) tree ||= [] # Folders && files && links diff --git a/app/models/dmsf_file_revision.rb b/app/models/dmsf_file_revision.rb index 5d22f1ec..c628fc82 100644 --- a/app/models/dmsf_file_revision.rb +++ b/app/models/dmsf_file_revision.rb @@ -19,6 +19,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +require 'digest/md5' + class DmsfFileRevision < ActiveRecord::Base unloadable belongs_to :dmsf_file @@ -159,6 +161,7 @@ class DmsfFileRevision < ActiveRecord::Base new_revision.source_revision = self new_revision.user = User.current new_revision.name = self.name + new_revision.digest = self.digest new_revision end @@ -262,4 +265,23 @@ class DmsfFileRevision < ActiveRecord::Base format + ext end + def self.create_digest(path) + begin + Digest::MD5.file(path).hexdigest + rescue Exception => e + Rails.logger.error e.message + nil + end + end + + def create_digest + begin + self.digest = Digest::MD5.file(self.disk_file).hexdigest + true + rescue Exception => e + Rails.logger.error e.message + false + end + end + end \ No newline at end of file diff --git a/app/views/dmsf_files/_revision_access.html.erb b/app/views/dmsf_files/_revision_access.html.erb index a4a736fb..e2dd74f4 100644 --- a/app/views/dmsf_files/_revision_access.html.erb +++ b/app/views/dmsf_files/_revision_access.html.erb @@ -22,23 +22,23 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. %> - +
- - - - + + + + <% revision.access_grouped.each do |access| %> - - - - + + + + <% end %> -
<%= l(:field_user) %><%= l(:heading_access_downloads_emails) %><%= l(:heading_access_first) %><%= l(:heading_access_last) %><%= l(:field_user) %><%= l(:heading_access_downloads_emails) %><%= l(:heading_access_first) %><%= l(:heading_access_last) %>
<%= link_to_user(access.user) %><%= access['count'] %><%= format_time(DmsfHelper::to_time(access.first_at)) %><%= format_time(DmsfHelper::to_time(access.last_at)) %><%= link_to_user(access.user) %><%= access.count %><%= format_time(access.first_at) %><%= format_time(access.last_at) %>
\ No newline at end of file + diff --git a/app/views/dmsf_files/show.html.erb b/app/views/dmsf_files/show.html.erb index ba2d2746..cd0f9484 100644 --- a/app/views/dmsf_files/show.html.erb +++ b/app/views/dmsf_files/show.html.erb @@ -98,70 +98,68 @@ <%= link_to(revision.user.name, user_path(revision.user)) if revision.user %> -
-
+
+

<%= label_tag('', l(:label_title)) %> <%= h(revision.title) %>

-
-
-

- <%= label_tag('', l(:label_file)) %> - <%= ("#{h(revision.dmsf_file.dmsf_folder.dmsf_path_str)}/") if revision.dmsf_file.dmsf_folder %><%= h(revision.name) %> -

-
-
- <% if revision.description.present? %> -

- <%= label_tag('', l(:label_description)) %> -

- <%= textilizable(revision.description) %> -
-

- <% end %> -
-
+ <% if revision.description.present? %> +

+ <%= label_tag('', l(:label_description)) %> +

+ <%= textilizable(revision.description) %> +
+

+ <% end %>

<%= label_tag('', l(:label_version)) %> <%= revision.major_version %>.<%= revision.minor_version %>

- <%= label_tag('', l(:link_workflow)) %> - <% wf = DmsfWorkflow.find_by_id(revision.dmsf_workflow_id) %> - <% if wf %> + <%= label_tag('', l(:label_size)) %> + <%= number_to_human_size(revision.size) %> +

+ <% wf = DmsfWorkflow.find_by_id(revision.dmsf_workflow_id) %> + <% if wf %> +

+ <%= label_tag('', l(:link_workflow)) %> <%= "#{wf.name} - " %> <%= link_to(revision.workflow_str(false), log_dmsf_workflow_path(:project_id => @project.id, :id => wf.id, :dmsf_file_revision_id => revision.id), :title => DmsfWorkflow.assignments_to_users_str(wf.next_assignments(revision.id)), :remote => true) %> - <% else %> - <%= revision.workflow_str(true) %> - <% end %> -

+

+ <% end %> + <% if revision.comment.present? %> +

+ <%= label_tag('', l(:label_comment)) %> +

+ <%= textilizable(revision.comment) %> +
+

+ <% end %>
+

+ <%= label_tag('', l(:label_file)) %> + <%= ("#{h(revision.dmsf_file.dmsf_folder.dmsf_path_str)}/") if revision.dmsf_file.dmsf_folder %><%= h(revision.name) %> +

<%= label_tag('', l(:label_mime)) %> <%= h(revision.mime_type) %>

-

- <%= label_tag('', l(:label_size)) %> - <%= number_to_human_size(revision.size) %> -

+ <% if revision.digest.present? %> +

+ <%= label_tag('', 'MD5') %> + <%= revision.digest %> +

+ <% end %> + <%= render 'dmsf/custom_fields', :object => revision %>
- <%= render 'dmsf/custom_fields', :object => revision %> - <% if revision.comment.present? %> -

- <%= label_tag('', l(:label_comment)) %> -

- <%= textilizable(revision.comment) %> -
-

- <% end %>
" style="display:none"> <%= render(:partial => 'revision_access', :locals => {:revision => revision}) if User.current.allowed_to?(:file_manipulation, @file.project) %>
@@ -208,7 +206,7 @@ } }); - $('.access-table').dataTable({ + $('.dmsf_list').dataTable({ 'bJQueryUI': true, 'oLanguage': { 'sUrl': '/plugin_assets/<%= :redmine_dmsf %>/javascripts/<%= url %>' diff --git a/db/migrate/20160421150501_add_digest_to_revision.rb b/db/migrate/20160421150501_add_digest_to_revision.rb new file mode 100644 index 00000000..a6babd0d --- /dev/null +++ b/db/migrate/20160421150501_add_digest_to_revision.rb @@ -0,0 +1,29 @@ +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-16 Karel Pičman +# +# This program 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 2 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +class AddDigestToRevision < ActiveRecord::Migration + def up + add_column :dmsf_file_revisions, :digest, :string, :limit => 40, :default => '', :null => false + end + + def down + remove_column :dmsf_file_revisions, :digest + end +end diff --git a/lib/tasks/dmsf_create_digests.rake b/lib/tasks/dmsf_create_digests.rake new file mode 100644 index 00000000..54a92118 --- /dev/null +++ b/lib/tasks/dmsf_create_digests.rake @@ -0,0 +1,63 @@ +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-16 Karel Pičman +# +# This program 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 2 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +desc <<-END_DESC +DMSF maintenance task + * Create missing MD5 digest for all file revisions + +Available options: + *dry_run - test, no changes to he database + +Example: + bundle exec rake redmine:dmsf_create_digests RAILS_ENV="production" + bundle exec rake redmine:dmsf_create_digests dry_run=1 RAILS_ENV="production" +END_DESC + +namespace :redmine do + task :dmsf_create_digests => :environment do + m = DmsfDigest.new + m.create_digests + end +end + +class DmsfDigest + + def initialize + @dry_run = ENV['dry_run'] + end + + def create_digests + revisions = DmsfFileRevision.where("digest IS NULL OR digest = ''").all + count = revisions.count + n = 0 + revisions.each_with_index do |rev, i| + if rev.create_digest + rev.save unless @dry_run + n += 1 + end + # Progress bar + print "\r#{i * 100 / count}%" + end + print "\r100%\n" + # Result + puts "#{n}/#{DmsfFileRevision.count} revisions updated." + end + +end