Add MD5 of each revision in the detail view of documents #527
This commit is contained in:
parent
8507ee9b09
commit
52f245e913
@ -139,10 +139,16 @@ 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
|
||||||
|
if last_revision.digest.blank?
|
||||||
|
revision.digest = DmsfFileRevision.create_digest last_revision.disk_file
|
||||||
|
else
|
||||||
|
revision.digest = last_revision.digest
|
||||||
|
end
|
||||||
else
|
else
|
||||||
revision.size = file_upload.size
|
revision.size = file_upload.size
|
||||||
revision.disk_filename = revision.new_storage_filename
|
revision.disk_filename = revision.new_storage_filename
|
||||||
revision.mime_type = Redmine::MimeType.of(file_upload.original_filename)
|
revision.mime_type = Redmine::MimeType.of(file_upload.original_filename)
|
||||||
|
revision.digest = DmsfFileRevision.create_digest file_upload.path
|
||||||
end
|
end
|
||||||
|
|
||||||
# Custom fields
|
# Custom fields
|
||||||
|
|||||||
@ -187,6 +187,7 @@ class DmsfUploadController < ApplicationController
|
|||||||
end
|
end
|
||||||
new_revision.mime_type = Redmine::MimeType.of(new_revision.name)
|
new_revision.mime_type = Redmine::MimeType.of(new_revision.name)
|
||||||
new_revision.size = File.size(commited_disk_filepath)
|
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.
|
# Need to save file first to generate id for it in case of creation.
|
||||||
# File id is needed to properly generate revision disk filename
|
# File id is needed to properly generate revision disk filename
|
||||||
|
|||||||
@ -67,17 +67,6 @@ module DmsfHelper
|
|||||||
return "#{Redmine::Utils.relative_url_root}/plugin_assets/#{plugin}/#{asset_type}/#{source}"
|
return "#{Redmine::Utils.relative_url_root}/plugin_assets/#{plugin}/#{asset_type}/#{source}"
|
||||||
end
|
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)
|
def self.dmsf_tree(parent, obj, tree = nil)
|
||||||
tree ||= []
|
tree ||= []
|
||||||
# Folders && files && links
|
# Folders && files && links
|
||||||
|
|||||||
@ -19,6 +19,8 @@
|
|||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require 'digest/md5'
|
||||||
|
|
||||||
class DmsfFileRevision < ActiveRecord::Base
|
class DmsfFileRevision < ActiveRecord::Base
|
||||||
unloadable
|
unloadable
|
||||||
belongs_to :dmsf_file
|
belongs_to :dmsf_file
|
||||||
@ -159,6 +161,7 @@ class DmsfFileRevision < ActiveRecord::Base
|
|||||||
new_revision.source_revision = self
|
new_revision.source_revision = self
|
||||||
new_revision.user = User.current
|
new_revision.user = User.current
|
||||||
new_revision.name = self.name
|
new_revision.name = self.name
|
||||||
|
new_revision.digest = self.digest
|
||||||
new_revision
|
new_revision
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -262,4 +265,23 @@ class DmsfFileRevision < ActiveRecord::Base
|
|||||||
format + ext
|
format + ext
|
||||||
end
|
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
|
end
|
||||||
@ -22,22 +22,22 @@
|
|||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<table class="display access-table list">
|
<table class="display list dmsf_list">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><%= l(:field_user) %></th>
|
<th class="dmsf_th"><%= l(:field_user) %></th>
|
||||||
<th><%= l(:heading_access_downloads_emails) %></th>
|
<th class="dmsf_th"><%= l(:heading_access_downloads_emails) %></th>
|
||||||
<th><%= l(:heading_access_first) %></th>
|
<th class="dmsf_th"><%= l(:heading_access_first) %></th>
|
||||||
<th><%= l(:heading_access_last) %></th>
|
<th class="dmsf_th"><%= l(:heading_access_last) %></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% revision.access_grouped.each do |access| %>
|
<% revision.access_grouped.each do |access| %>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%= link_to_user(access.user) %></td>
|
<td class="dmsf_author"><%= link_to_user(access.user) %></td>
|
||||||
<td class="dmsf_version"><%= access['count'] %></td>
|
<td class="dmsf_version"><%= access.count %></td>
|
||||||
<td class="dmsf_modified"><%= format_time(DmsfHelper::to_time(access.first_at)) %></td>
|
<td class="dmsf_modified"><%= format_time(access.first_at) %></td>
|
||||||
<td class="dmsf_modified"><%= format_time(DmsfHelper::to_time(access.last_at)) %></td>
|
<td class="dmsf_modified"><%= format_time(access.last_at) %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -98,21 +98,13 @@
|
|||||||
<%= link_to(revision.user.name, user_path(revision.user)) if revision.user %>
|
<%= link_to(revision.user.name, user_path(revision.user)) if revision.user %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dmsf_revision_inner_box">
|
<div class="attributes dmsf_revision_inner_box">
|
||||||
<div class="clear">
|
<div class="splitcontent">
|
||||||
<div class="splitcontentleft">
|
<div class="splitcontentleft">
|
||||||
<p>
|
<p>
|
||||||
<%= label_tag('', l(:label_title)) %>
|
<%= label_tag('', l(:label_title)) %>
|
||||||
<%= h(revision.title) %>
|
<%= h(revision.title) %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
<div class="splitcontentright">
|
|
||||||
<p>
|
|
||||||
<%= label_tag('', l(:label_file)) %>
|
|
||||||
<%= ("#{h(revision.dmsf_file.dmsf_folder.dmsf_path_str)}/") if revision.dmsf_file.dmsf_folder %><%= h(revision.name) %>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<% if revision.description.present? %>
|
<% if revision.description.present? %>
|
||||||
<p>
|
<p>
|
||||||
<%= label_tag('', l(:label_description)) %>
|
<%= label_tag('', l(:label_description)) %>
|
||||||
@ -121,39 +113,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="clear">
|
|
||||||
<div class="splitcontentleft">
|
|
||||||
<p>
|
<p>
|
||||||
<%= label_tag('', l(:label_version)) %>
|
<%= label_tag('', l(:label_version)) %>
|
||||||
<%= revision.major_version %>.<%= revision.minor_version %>
|
<%= revision.major_version %>.<%= revision.minor_version %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= label_tag('', l(:link_workflow)) %>
|
<%= label_tag('', l(:label_size)) %>
|
||||||
|
<%= number_to_human_size(revision.size) %>
|
||||||
|
</p>
|
||||||
<% wf = DmsfWorkflow.find_by_id(revision.dmsf_workflow_id) %>
|
<% wf = DmsfWorkflow.find_by_id(revision.dmsf_workflow_id) %>
|
||||||
<% if wf %>
|
<% if wf %>
|
||||||
|
<p>
|
||||||
|
<%= label_tag('', l(:link_workflow)) %>
|
||||||
<%= "#{wf.name} - " %>
|
<%= "#{wf.name} - " %>
|
||||||
<%= link_to(revision.workflow_str(false),
|
<%= link_to(revision.workflow_str(false),
|
||||||
log_dmsf_workflow_path(:project_id => @project.id,
|
log_dmsf_workflow_path(:project_id => @project.id,
|
||||||
:id => wf.id, :dmsf_file_revision_id => revision.id),
|
:id => wf.id, :dmsf_file_revision_id => revision.id),
|
||||||
:title => DmsfWorkflow.assignments_to_users_str(wf.next_assignments(revision.id)),
|
:title => DmsfWorkflow.assignments_to_users_str(wf.next_assignments(revision.id)),
|
||||||
:remote => true) %>
|
:remote => true) %>
|
||||||
<% else %>
|
</p>
|
||||||
<%= revision.workflow_str(true) %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="splitcontentright">
|
|
||||||
<p>
|
|
||||||
<%= label_tag('', l(:label_mime)) %>
|
|
||||||
<%= h(revision.mime_type) %>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<%= label_tag('', l(:label_size)) %>
|
|
||||||
<%= number_to_human_size(revision.size) %>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<%= render 'dmsf/custom_fields', :object => revision %>
|
|
||||||
<% if revision.comment.present? %>
|
<% if revision.comment.present? %>
|
||||||
<p>
|
<p>
|
||||||
<%= label_tag('', l(:label_comment)) %>
|
<%= label_tag('', l(:label_comment)) %>
|
||||||
@ -162,6 +141,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="splitcontentright">
|
||||||
|
<p>
|
||||||
|
<%= label_tag('', l(:label_file)) %>
|
||||||
|
<%= ("#{h(revision.dmsf_file.dmsf_folder.dmsf_path_str)}/") if revision.dmsf_file.dmsf_folder %><%= h(revision.name) %>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<%= label_tag('', l(:label_mime)) %>
|
||||||
|
<%= h(revision.mime_type) %>
|
||||||
|
</p>
|
||||||
|
<% if revision.digest.present? %>
|
||||||
|
<p>
|
||||||
|
<%= label_tag('', 'MD5') %>
|
||||||
|
<%= revision.digest %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<%= render 'dmsf/custom_fields', :object => revision %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="<%= "revision_access-#{revision.id}" %>" style="display:none">
|
<div id="<%= "revision_access-#{revision.id}" %>" style="display:none">
|
||||||
<%= render(:partial => 'revision_access', :locals => {:revision => revision}) if User.current.allowed_to?(:file_manipulation, @file.project) %>
|
<%= render(:partial => 'revision_access', :locals => {:revision => revision}) if User.current.allowed_to?(:file_manipulation, @file.project) %>
|
||||||
</div>
|
</div>
|
||||||
@ -208,7 +206,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.access-table').dataTable({
|
$('.dmsf_list').dataTable({
|
||||||
'bJQueryUI': true,
|
'bJQueryUI': true,
|
||||||
'oLanguage': {
|
'oLanguage': {
|
||||||
'sUrl': '/plugin_assets/<%= :redmine_dmsf %>/javascripts/<%= url %>'
|
'sUrl': '/plugin_assets/<%= :redmine_dmsf %>/javascripts/<%= url %>'
|
||||||
|
|||||||
29
db/migrate/20160421150501_add_digest_to_revision.rb
Normal file
29
db/migrate/20160421150501_add_digest_to_revision.rb
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
#
|
||||||
|
# Redmine plugin for Document Management System "Features"
|
||||||
|
#
|
||||||
|
# Copyright (C) 2011-16 Karel Pičman <karel.picman@kontron.com>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
63
lib/tasks/dmsf_create_digests.rake
Normal file
63
lib/tasks/dmsf_create_digests.rake
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
#
|
||||||
|
# Redmine plugin for Document Management System "Features"
|
||||||
|
#
|
||||||
|
# Copyright (C) 2011-16 Karel Pičman <karel.picman@kontron.com>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
Loading…
x
Reference in New Issue
Block a user