Status 404 after moving the folder to another project #1106
This commit is contained in:
parent
0b750831d2
commit
ecec07b520
@ -83,8 +83,6 @@ class DmsfContextMenusController < ApplicationController
|
||||
|
||||
def find_folder
|
||||
@folder = DmsfFolder.find params[:folder_id] if params[:folder_id].present?
|
||||
rescue DmsfAccessError
|
||||
render_403
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
@ -30,13 +30,13 @@ class DmsfController < ApplicationController
|
||||
:autocomplete_for_user]
|
||||
before_action :find_parent, only: [:new, :create]
|
||||
before_action :permissions
|
||||
# also try to lookup folder by title if this is API call
|
||||
# Also try to lookup folder by title if this is an API call
|
||||
before_action :find_folder_by_title, only: [:show]
|
||||
before_action :get_query, only: [:expand_folder, :show, :trash]
|
||||
|
||||
accept_api_auth :show, :create, :save, :delete
|
||||
|
||||
helper :all # TODO: Is it needed?
|
||||
helper :custom_fields
|
||||
helper :dmsf_folder_permissions
|
||||
helper :queries
|
||||
include QueriesHelper
|
||||
@ -48,7 +48,6 @@ class DmsfController < ApplicationController
|
||||
|
||||
def expand_folder
|
||||
@idnt = params[:idnt].present? ? params[:idnt].to_i + 1 : 0
|
||||
#@query = retrieve_query(DmsfQuery, true)
|
||||
@query.dmsf_folder_id = @folder.id
|
||||
@query.deleted = false
|
||||
respond_to do |format|
|
||||
@ -62,8 +61,6 @@ class DmsfController < ApplicationController
|
||||
@folder_manipulation_allowed = User.current.allowed_to?(:folder_manipulation, @project)
|
||||
@file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project)
|
||||
@trash_enabled = @folder_manipulation_allowed && @file_manipulation_allowed
|
||||
#use_session = !request.format.csv?
|
||||
#@query = retrieve_query(DmsfQuery, use_session)
|
||||
@query.dmsf_folder_id = @folder ? @folder.id : nil
|
||||
@query.deleted = false
|
||||
if (@folder && @folder.deleted?) || (params[:folder_title].present? && !@folder)
|
||||
@ -89,7 +86,6 @@ class DmsfController < ApplicationController
|
||||
@folder_manipulation_allowed = User.current.allowed_to? :folder_manipulation, @project
|
||||
@file_manipulation_allowed = User.current.allowed_to? :file_manipulation, @project
|
||||
@file_delete_allowed = User.current.allowed_to? :file_delete, @project
|
||||
#@query = retrieve_query(DmsfQuery, true)
|
||||
@query.deleted = true
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
@ -604,9 +600,7 @@ class DmsfController < ApplicationController
|
||||
end
|
||||
|
||||
def find_folder
|
||||
@folder = DmsfFolder.find_by!(id: params[:folder_id], project_id: @project.id) if params[:folder_id].present?
|
||||
rescue DmsfAccessError
|
||||
render_403
|
||||
@folder = DmsfFolder.find(params[:folder_id]) if params[:folder_id].present?
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
@ -38,24 +38,22 @@ class DmsfFoldersCopyController < ApplicationController
|
||||
|
||||
def copy
|
||||
new_folder = @folder.copy_to(@target_project, @target_folder)
|
||||
unless new_folder.errors.empty?
|
||||
if new_folder.errors.empty?
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to dmsf_folder_path(id: @target_project, folder_id: new_folder)
|
||||
else
|
||||
flash[:error] = new_folder.errors.full_messages.to_sentence
|
||||
redirect_to action: 'new', id: @folder, target_project_id: @target_project, target_folder_id: @target_folder
|
||||
return
|
||||
redirect_to :back
|
||||
end
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to dmsf_folder_path(id: @target_project, folder_id: new_folder)
|
||||
end
|
||||
|
||||
def move
|
||||
@folder.project = @target_project
|
||||
@folder.dmsf_folder = @target_folder
|
||||
if @folder.save
|
||||
if @folder.move_to(@target_project, @target_folder)
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to dmsf_folder_path(id: @target_project, folder_id: @folder)
|
||||
else
|
||||
flash[:error] = @folder.errors.full_messages.to_sentence
|
||||
redirect_to action: 'new', id: @folder, target_project_id: @target_project, target_folder_id: @target_folder
|
||||
redirect_to :back
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -155,7 +155,8 @@ class DmsfLinksController < ApplicationController
|
||||
if params[:dmsf_link][:dmsf_file_id].present?
|
||||
redirect_to dmsf_file_path(@dmsf_link.target_file)
|
||||
else
|
||||
redirect_to edit_dmsf_path(id: params[:dmsf_link][:project_id], folder_id: params[:dmsf_link][:dmsf_folder_id])
|
||||
folder = @dmsf_link.target_folder.dmsf_folder if @dmsf_link.target_folder
|
||||
redirect_to dmsf_folder_path(id: @project, folder_id: folder)
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
@ -235,8 +235,12 @@ class DmsfFile < ActiveRecord::Base
|
||||
errors[:base] << l(:error_file_is_locked)
|
||||
return false
|
||||
end
|
||||
unless last_revision
|
||||
errors[:base] << l(:error_at_least_one_revision_must_be_present)
|
||||
return false
|
||||
end
|
||||
source = "#{project.identifier}:#{dmsf_path_str}"
|
||||
self.project_id = project.id
|
||||
self.project = project
|
||||
self.dmsf_folder = folder
|
||||
new_revision = last_revision.clone
|
||||
new_revision.workflow = nil
|
||||
@ -251,12 +255,12 @@ class DmsfFile < ActiveRecord::Base
|
||||
last_revision.custom_values.each do |cv|
|
||||
new_revision.custom_values << CustomValue.new({ custom_field: cv.custom_field, value: cv.value })
|
||||
end
|
||||
set_last_revision(new_revision)
|
||||
set_last_revision new_revision
|
||||
save && new_revision.save
|
||||
end
|
||||
|
||||
def copy_to(project, folder = nil)
|
||||
copy_to_filename(project, folder, name)
|
||||
copy_to_filename project, folder, name
|
||||
end
|
||||
|
||||
def copy_to_filename(project, folder, filename)
|
||||
|
||||
@ -247,6 +247,23 @@ class DmsfFolder < ActiveRecord::Base
|
||||
projects
|
||||
end
|
||||
|
||||
def move_to(target_project, target_folder)
|
||||
if self.project != target_project
|
||||
dmsf_files.visible.find_each do |f|
|
||||
f.move_to target_project, f.dmsf_folder
|
||||
end
|
||||
dmsf_folders.visible.find_each do |s|
|
||||
s.move_to target_project, s.dmsf_folder
|
||||
end
|
||||
dmsf_links.visible.find_each do |l|
|
||||
l.move_to target_project, l.dmsf_folder
|
||||
end
|
||||
self.project = target_project
|
||||
end
|
||||
self.dmsf_folder = target_folder
|
||||
save
|
||||
end
|
||||
|
||||
def copy_to(project, folder)
|
||||
new_folder = DmsfFolder.new
|
||||
new_folder.dmsf_folder = folder ? folder : nil
|
||||
@ -254,7 +271,6 @@ class DmsfFolder < ActiveRecord::Base
|
||||
new_folder.title = title
|
||||
new_folder.description = description
|
||||
new_folder.user = User.current
|
||||
|
||||
new_folder.custom_values = []
|
||||
custom_values.each do |cv|
|
||||
v = CustomValue.new
|
||||
@ -262,36 +278,22 @@ class DmsfFolder < ActiveRecord::Base
|
||||
v.value = cv.value
|
||||
new_folder.custom_values << v
|
||||
end
|
||||
|
||||
unless new_folder.save
|
||||
Rails.logger.error new_folder.errors.full_messages.to_sentence
|
||||
return new_folder
|
||||
end
|
||||
|
||||
dmsf_files.visible.find_each do |f|
|
||||
f.copy_to project, new_folder
|
||||
end
|
||||
|
||||
dmsf_folders.visible.find_each do |s|
|
||||
s.copy_to project, new_folder
|
||||
end
|
||||
|
||||
folder_links.visible.find_each do |l|
|
||||
dmsf_links.visible.find_each do |l|
|
||||
l.copy_to project, new_folder
|
||||
end
|
||||
|
||||
file_links.visible.find_each do |l|
|
||||
l.copy_to project, new_folder
|
||||
end
|
||||
|
||||
url_links.visible.find_each do |l|
|
||||
l.copy_to project, new_folder
|
||||
end
|
||||
|
||||
dmsf_folder_permissions.find_each do |p|
|
||||
p.copy_to new_folder
|
||||
end
|
||||
|
||||
new_folder
|
||||
end
|
||||
|
||||
|
||||
@ -79,13 +79,6 @@ class DmsfLink < ActiveRecord::Base
|
||||
@target_project
|
||||
end
|
||||
|
||||
def folder
|
||||
if !@folder && dmsf_folder_id
|
||||
@folder = DmsfFolder.find_by(id: dmsf_folder_id)
|
||||
end
|
||||
@folder
|
||||
end
|
||||
|
||||
def title
|
||||
name
|
||||
end
|
||||
@ -114,6 +107,12 @@ class DmsfLink < ActiveRecord::Base
|
||||
path
|
||||
end
|
||||
|
||||
def move_to(target_project, target_folder)
|
||||
self.project = target_project
|
||||
self.dmsf_folder = target_folder
|
||||
save
|
||||
end
|
||||
|
||||
def copy_to(project, folder)
|
||||
link = DmsfLink.new
|
||||
link.target_project_id = target_project_id
|
||||
@ -128,8 +127,8 @@ class DmsfLink < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def container
|
||||
if folder && folder.system
|
||||
Issue.find_by(id: folder.title)
|
||||
if dmsf_folder && dmsf_folder.system
|
||||
Issue.find_by id: dmsf_folder.title
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -189,9 +189,13 @@ class DmsfQuery < Query
|
||||
joins('LEFT JOIN users ON dmsf_folders.user_id = users.id').
|
||||
visible(!deleted)
|
||||
if deleted
|
||||
scope.where(dmsf_folders: { project_id: project.id, deleted: deleted })
|
||||
scope.where dmsf_folders: { project_id: project.id, deleted: deleted }
|
||||
else
|
||||
scope.where(dmsf_folders: { project_id: project.id, dmsf_folder_id: dmsf_folder_id, deleted: deleted })
|
||||
if dmsf_folder_id
|
||||
scope.where dmsf_folders: { dmsf_folder_id: dmsf_folder_id, deleted: deleted }
|
||||
else
|
||||
scope.where dmsf_folders: { project_id: project.id, dmsf_folder_id: nil, deleted: deleted }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -204,7 +208,7 @@ class DmsfQuery < Query
|
||||
select(%{
|
||||
dmsf_links.id AS id,
|
||||
COALESCE(dmsf_folders.project_id, dmsf_links.project_id) AS project_id,
|
||||
CAST(NULL AS #{ActiveRecord::Base.connection.type_to_sql(:decimal)}) AS revision_id,
|
||||
dmsf_links.target_id AS revision_id,
|
||||
dmsf_links.name AS title,
|
||||
dmsf_folders.title AS filename,
|
||||
CAST(NULL AS #{ActiveRecord::Base.connection.type_to_sql(:decimal)}) AS size,
|
||||
@ -222,10 +226,13 @@ class DmsfQuery < Query
|
||||
joins('LEFT JOIN dmsf_folders ON dmsf_links.target_id = dmsf_folders.id').
|
||||
joins('LEFT JOIN users ON users.id = COALESCE(dmsf_folders.user_id, dmsf_links.user_id)')
|
||||
if deleted
|
||||
scope.where(dmsf_links: { target_type: 'DmsfFolder', project_id: project.id, deleted: deleted })
|
||||
scope.where dmsf_links: { target_type: 'DmsfFolder', project_id: project.id, deleted: deleted }
|
||||
else
|
||||
scope.where(dmsf_links: { target_type: 'DmsfFolder', project_id: project.id, dmsf_folder_id: dmsf_folder_id,
|
||||
deleted: deleted })
|
||||
if dmsf_folder_id
|
||||
scope.where dmsf_links: { target_type: 'DmsfFolder', dmsf_folder_id: dmsf_folder_id, deleted: deleted }
|
||||
else
|
||||
scope.where dmsf_links: { target_type: 'DmsfFolder', project_id: project.id, dmsf_folder_id: nil, deleted: deleted }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -257,9 +264,14 @@ class DmsfQuery < Query
|
||||
joins('LEFT JOIN users ON dmsf_file_revisions.user_id = users.id ').
|
||||
where('dmsf_file_revisions.created_at = (SELECT MAX(r.created_at) FROM dmsf_file_revisions r WHERE r.dmsf_file_id = dmsf_file_revisions.dmsf_file_id)')
|
||||
if deleted
|
||||
scope.where(dmsf_files: { project_id: project.id, deleted: deleted })
|
||||
scope.where dmsf_files: { project_id: project.id, deleted: deleted }
|
||||
else
|
||||
scope.where(dmsf_files: { project_id: project.id, dmsf_folder_id: dmsf_folder_id, deleted: deleted })
|
||||
# Consider files belonging to the folder but with wrong project (#1106)
|
||||
if dmsf_folder_id
|
||||
scope.where dmsf_files: { dmsf_folder_id: dmsf_folder_id, deleted: deleted }
|
||||
else
|
||||
scope.where dmsf_files: { project_id: project.id, dmsf_folder_id: nil, deleted: deleted }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -272,7 +284,7 @@ class DmsfQuery < Query
|
||||
select(%{
|
||||
dmsf_links.id AS id,
|
||||
dmsf_files.project_id AS project_id,
|
||||
dmsf_file_revisions.id AS revision_id,
|
||||
dmsf_files.id AS revision_id,
|
||||
dmsf_links.name AS title,
|
||||
dmsf_file_revisions.name AS filename,
|
||||
dmsf_file_revisions.size AS size,
|
||||
@ -292,9 +304,13 @@ class DmsfQuery < Query
|
||||
joins('LEFT JOIN users ON dmsf_file_revisions.user_id = users.id ').
|
||||
where('dmsf_file_revisions.created_at = (SELECT MAX(r.created_at) FROM dmsf_file_revisions r WHERE r.dmsf_file_id = dmsf_file_revisions.dmsf_file_id)')
|
||||
if deleted
|
||||
scope.where(project_id: project.id, deleted: deleted)
|
||||
scope.where project_id: project.id, deleted: deleted
|
||||
else
|
||||
scope.where(project_id: project.id, dmsf_folder_id: dmsf_folder_id, deleted: deleted)
|
||||
if dmsf_folder_id
|
||||
scope.where dmsf_folder_id: dmsf_folder_id, deleted: deleted
|
||||
else
|
||||
scope.where project_id: project.id, dmsf_folder_id: nil, deleted: deleted
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -324,9 +340,13 @@ class DmsfQuery < Query
|
||||
1 AS sort #{cf_columns}}).
|
||||
joins('LEFT JOIN users ON dmsf_links.user_id = users.id ')
|
||||
if deleted
|
||||
scope.where(target_type: 'DmsfUrl', project_id: project.id, deleted: deleted)
|
||||
scope.where target_type: 'DmsfUrl', project_id: project.id, deleted: deleted
|
||||
else
|
||||
scope.where(target_type: 'DmsfUrl', project_id: project.id, dmsf_folder_id: dmsf_folder_id, deleted: deleted)
|
||||
if dmsf_folder_id
|
||||
scope.where target_type: 'DmsfUrl', dmsf_folder_id: dmsf_folder_id, deleted: deleted
|
||||
else
|
||||
scope.where target_type: 'DmsfUrl', project_id: project.id, dmsf_folder_id: nil, deleted: deleted
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -47,11 +47,6 @@
|
||||
class: 'icon icon-email-add') %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<%= link_to(l(:label_link_to),
|
||||
new_dmsf_link_path(project_id: @project.id, dmsf_folder_id: @folder.id, type: 'link_to'),
|
||||
title: l(:title_create_link), class: 'icon icon-link') %>
|
||||
<%= link_to("#{l(:button_copy)}/#{l(:button_move)}", copy_folder_path(id: @folder),
|
||||
title: l(:title_copy), class: 'icon icon-copy') %>
|
||||
<% unless @folder.locked? %>
|
||||
<%= link_to(l(:button_delete), delete_dmsf_path(id: @project, folder_id: @folder),
|
||||
data: { confirm: l(:text_are_you_sure) },
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
<% html_title l(:dmsf) %>
|
||||
<div class="contextual">
|
||||
<% if @file_manipulation_allowed && !@locked_for_user && !@system_folder %>
|
||||
<%= link_to l(:label_attachment_new), multi_dmsf_upload_path(id: @project, dmsf_folder_id: @folder),
|
||||
<%= link_to l(:label_attachment_new), multi_dmsf_upload_path(id: @project, folder_id: @folder),
|
||||
class: 'icon icon-add' %>
|
||||
<% end %>
|
||||
<% if defined?(EasyExtensions) %>
|
||||
|
||||
@ -22,36 +22,40 @@
|
||||
|
||||
<li>
|
||||
<%= context_menu_link l(:button_edit), edit_dmsf_path(id: project, folder_id: dmsf_folder),
|
||||
class: 'icon icon-edit',
|
||||
disabled: !allowed || locked %>
|
||||
class: 'icon icon-edit', disabled: !allowed || locked %>
|
||||
</li>
|
||||
<li>
|
||||
<%= context_menu_link "#{l(:button_copy)}/#{l(:button_move)}", copy_folder_path(id: dmsf_folder),
|
||||
class: 'icon icon-copy', disabled: !allowed || locked %>
|
||||
</li>
|
||||
<li>
|
||||
<%= context_menu_link l(:label_link_to),
|
||||
new_dmsf_link_path(project_id: project.id, dmsf_folder_id: dmsf_folder.id, type: 'link_to'),
|
||||
class: 'icon icon-link', disabled: !allowed || locked %>
|
||||
</li>
|
||||
<li>
|
||||
<% if locked %>
|
||||
<%= context_menu_link l(:button_unlock), unlock_dmsf_path(id: project, folder_id: dmsf_folder),
|
||||
class: 'icon icon-unlock',
|
||||
disabled: !allowed || !unlockable %>
|
||||
class: 'icon icon-unlock', disabled: !allowed || !unlockable %>
|
||||
<% else %>
|
||||
<%= context_menu_link l(:button_lock), lock_dmsf_path(id: project, folder_id: dmsf_folder),
|
||||
class: 'icon icon-lock',
|
||||
disabled: !allowed %>
|
||||
class: 'icon icon-lock', disabled: !allowed %>
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<% if dmsf_folder.notification %>
|
||||
<%= context_menu_link l(:label_notifications_off), notify_deactivate_dmsf_path(id: project, folder_id: dmsf_folder),
|
||||
class: 'icon icon-email',
|
||||
disabled: !allowed || locked || !dmsf_folder.notification? %>
|
||||
class: 'icon icon-email', disabled: !allowed || locked || !dmsf_folder.notification? %>
|
||||
<% else %>
|
||||
<%= context_menu_link l(:label_notifications_on), notify_activate_dmsf_path(id: project, folder_id: dmsf_folder),
|
||||
class: 'icon icon-email-add',
|
||||
disabled: !allowed || locked || dmsf_folder.notification? %>
|
||||
class: 'icon icon-email-add', disabled: !allowed || locked || dmsf_folder.notification? %>
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<%= context_menu_link l(:button_delete),
|
||||
dmsf_link ? dmsf_link_path(dmsf_link) : delete_dmsf_path(id: project, folder_id: dmsf_folder),
|
||||
data: { confirm: l(:text_are_you_sure) }, method: :delete, class: 'icon icon-del', id: 'dmsf-cm-delete',
|
||||
disabled: !allowed || locked || !dmsf_folder.empty? %>
|
||||
disabled: !allowed || locked || (dmsf_link ? false : !dmsf_folder.empty?) %>
|
||||
</li>
|
||||
<li>
|
||||
<%= context_menu_link l(:button_download), entries_operations_dmsf_path(id: project, folder_id: folder,
|
||||
|
||||
@ -32,8 +32,8 @@
|
||||
<div class="box tabular">
|
||||
<% if (@type == 'link_from') && !@container %>
|
||||
<p>
|
||||
<%= radio_button_tag(:external_link, 'false', true) %> <%= l(:label_internal) %><br/>
|
||||
<%= radio_button_tag(:external_link, 'true', false) %> <%= l(:label_external) %>
|
||||
<%= radio_button_tag :external_link, 'false', true %> <%= l(:label_internal) %><br/>
|
||||
<%= radio_button_tag :external_link, 'true', false %> <%= l(:label_external) %>
|
||||
</p>
|
||||
<% end %>
|
||||
<div id="dmsf_link_internal">
|
||||
@ -44,9 +44,9 @@
|
||||
<% else %>
|
||||
<label for="dmsf_link[target_project_id]"><%= l(:label_target_project) %></label>
|
||||
<% end %>
|
||||
<%= select_tag('dmsf_link[target_project_id]',
|
||||
<%= select_tag 'dmsf_link[target_project_id]',
|
||||
project_tree_options_for_select(DmsfFile.allowed_target_projects_on_copy,
|
||||
selected: @dmsf_link.target_project)) %>
|
||||
selected: @dmsf_link.target_project) %>
|
||||
<%= late_javascript_tag do %>
|
||||
$('#dmsf_link_target_project_id').change(function(){
|
||||
$.ajax({
|
||||
@ -60,7 +60,7 @@
|
||||
<% end %>
|
||||
<p>
|
||||
<% if @type == 'link_from' %>
|
||||
<%= label_tag('dmsf_link[target_folder_id]', l(:label_source_folder)) %>
|
||||
<%= label_tag 'dmsf_link[target_folder_id]', l(:label_source_folder) %>
|
||||
<% else %>
|
||||
<label for="dmsf_link_target_folder_id">
|
||||
<%= l(:label_target_folder) %> <%= ' #' if @fast_links %>
|
||||
@ -71,9 +71,8 @@
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if !@fast_links || (@type != 'link_to') %>
|
||||
<%= select_tag('dmsf_link[target_folder_id]',
|
||||
folder_tree_options_for_select(DmsfFolder.directory_tree(@dmsf_link.target_project),
|
||||
selected: @target_folder_id)) %>
|
||||
<%= select_tag 'dmsf_link[target_folder_id]',
|
||||
folder_tree_options_for_select(DmsfFolder.directory_tree(@dmsf_link.target_project)) %>
|
||||
<%= late_javascript_tag do %>
|
||||
$('#dmsf_link_target_folder_id').change(function(){
|
||||
$.ajax({
|
||||
@ -87,10 +86,9 @@
|
||||
</p>
|
||||
<% if @type == 'link_from' %>
|
||||
<p>
|
||||
<%= label_tag('dmsf_link[target_file_id]', l(:field_target_file)) %>
|
||||
<%= label_tag 'dmsf_link[target_file_id]', l(:field_target_file) %>
|
||||
<% files = files_for_select(@dmsf_link.target_project.id, @target_folder_id) %>
|
||||
<%= select_tag('dmsf_link[target_file_id]',
|
||||
options_for_select(DmsfFolder.file_list(files)), required: modal) %>
|
||||
<%= select_tag 'dmsf_link[target_file_id]', options_for_select(DmsfFolder.file_list(files)), required: modal %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@ -72,6 +72,7 @@ if Redmine::Plugin.installed? :redmine_dmsf
|
||||
|
||||
get '/projects/:id/dmsf/upload/multi_upload', controller: 'dmsf_upload', action: 'multi_upload', as: 'multi_dmsf_upload'
|
||||
post '/projects/:id/dmsf/upload/files', controller: 'dmsf_upload', action: 'upload_files'
|
||||
get '/projects/:id/dmsf/upload/files', controller: 'dmsf_upload', action: 'upload_files'
|
||||
post '/projects/:id/dmsf/upload/file', controller: 'dmsf_upload', action: 'upload_file'
|
||||
post '/projects/:id/dmsf/upload', controller: 'dmsf_upload', action: 'upload'
|
||||
post '/projects/:id/dmsf/upload/commit', controller: 'dmsf_upload', action: 'commit_files'
|
||||
|
||||
28
db/migrate/20200423071301_add_indexes_on_dmsf_folder_id.rb
Normal file
28
db/migrate/20200423071301_add_indexes_on_dmsf_folder_id.rb
Normal file
@ -0,0 +1,28 @@
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright © 2011-20 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 AddIndexesOnDmsfFolderId < ActiveRecord::Migration[5.2]
|
||||
|
||||
def change
|
||||
add_index :dmsf_files, :dmsf_folder_id
|
||||
add_index :dmsf_links, :dmsf_folder_id
|
||||
end
|
||||
|
||||
end
|
||||
@ -76,7 +76,7 @@ module RedmineDmsf
|
||||
else
|
||||
tag = "<span class=\"dmsf_expander\" onclick=\"dmsfToggle('#{item.id}','#{item.id}span','#{escape_javascript(expand_folder_dmsf_path)}')\"></span>".html_safe +
|
||||
link_to(h(value),
|
||||
dmsf_folder_path(id: item.project_id, folder_id: item.id),
|
||||
dmsf_folder_path(id: item.project, folder_id: item.id),
|
||||
class: 'icon icon-folder',
|
||||
title: h(value))
|
||||
end
|
||||
@ -86,8 +86,9 @@ module RedmineDmsf
|
||||
tag = content_tag('span', value, class: 'icon icon-folder')
|
||||
else
|
||||
tag = "<span class=\"dmsf_expander\"></span>".html_safe +
|
||||
# For links we use revision_id containing dmsf_folder.id in fact
|
||||
link_to(h(value),
|
||||
dmsf_folder_path(id: item.project_id, folder_id: item.id),
|
||||
dmsf_folder_path(id: item.project, folder_id: item.revision_id),
|
||||
class: 'icon icon-folder',
|
||||
title: h(value))
|
||||
end
|
||||
@ -96,7 +97,8 @@ module RedmineDmsf
|
||||
if item.deleted && (item.deleted > 0)
|
||||
tag = content_tag('span', value, class: "icon icon-file #{DmsfHelper.filetype_css(item.filename)}")
|
||||
else
|
||||
file_view_url = url_for({ controller: :dmsf_files, action: 'view', id: item.id })
|
||||
# For links we use revision_id containing dmsf_file.id in fact
|
||||
file_view_url = url_for({ controller: :dmsf_files, action: 'view', id: (item.type == 'file') ? item.id : item.revision_id })
|
||||
content_type = Redmine::MimeType.of(value)
|
||||
content_type = 'application/octet-stream' if content_type.blank?
|
||||
tag = "<span class=\"dmsf_expander\"></span>".html_safe +
|
||||
|
||||
@ -31,7 +31,7 @@ module RedmineDmsf
|
||||
def initialize(path, request, response, options)
|
||||
@folder = nil
|
||||
@file = nil
|
||||
super(path, request, response, options)
|
||||
super path, request, response, options
|
||||
end
|
||||
|
||||
# Here we make sure our folder and file methods are not aliased - it should shave a few cycles off of processing
|
||||
@ -227,64 +227,52 @@ module RedmineDmsf
|
||||
resource = dest.is_a?(ResourceProxy) ? dest.resource : dest
|
||||
return PreconditionFailed if !resource.is_a?(DmsfResource) || resource.project.nil?
|
||||
parent = resource.parent
|
||||
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
|
||||
|
||||
if !parent.exist? || (!User.current.admin? && (!DmsfFolder.permissions?(folder, false) ||
|
||||
!DmsfFolder.permissions?(parent.folder, false)))
|
||||
raise Forbidden
|
||||
end
|
||||
if collection?
|
||||
|
||||
if dest.exist?
|
||||
return overwrite ? NotImplemented : PreconditionFailed
|
||||
end
|
||||
|
||||
# At the moment we don't support cross project destinations
|
||||
return NotImplemented unless (project.id == resource.project.id)
|
||||
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project)
|
||||
raise Forbidden unless DmsfFolder.permissions?(folder, false)
|
||||
|
||||
if !User.current.admin? && (!User.current.allowed_to?(:folder_manipulation, project) ||
|
||||
!User.current.allowed_to?(:folder_manipulation, resource.project))
|
||||
raise Forbidden
|
||||
end
|
||||
# Current object is a folder, so now we need to figure out information about Destination
|
||||
if dest.exist?
|
||||
return overwrite ? NotImplemented : PreconditionFailed
|
||||
else
|
||||
if parent.projectless_path == '/' # Project root
|
||||
folder.dmsf_folder_id = nil
|
||||
else
|
||||
return PreconditionFailed unless parent.exist? && parent.folder
|
||||
folder.dmsf_folder_id = parent.folder.id
|
||||
end
|
||||
folder.title = resource.basename
|
||||
folder.save ? Created : PreconditionFailed
|
||||
folder.move_to(resource.project, parent.folder) ? Created : PreconditionFailed
|
||||
end
|
||||
else
|
||||
raise Forbidden unless User.current.admin? ||
|
||||
User.current.allowed_to?(:folder_manipulation, project) ||
|
||||
User.current.allowed_to?(:folder_manipulation, resource.project)
|
||||
|
||||
if !User.current.admin? && (!User.current.allowed_to?(:file_manipulation, project) ||
|
||||
!User.current.allowed_to?(:file_manipulation, resource.project))
|
||||
raise Forbidden
|
||||
end
|
||||
if dest.exist?
|
||||
return PreconditionFailed unless overwrite
|
||||
if (project == resource.project) && file.name.match(/.\.tmp$/i)
|
||||
# Renaming a *.tmp file to an existing file in the same project, probably Office that is saving a file.
|
||||
Rails.logger.info "WebDAV MOVE: #{file.name} -> #{resource.basename} (exists), possible MSOffice rename from .tmp when saving"
|
||||
|
||||
if resource.file.last_revision.size == 0 || reuse_version_for_locked_file(resource.file)
|
||||
# Last revision in the destination has zero size so reuse that revision
|
||||
new_revision = resource.file.last_revision
|
||||
else
|
||||
# Create a new revison by cloning the last revision in the destination
|
||||
new_revision = resource.file.last_revision.clone
|
||||
new_revision.increase_version(1)
|
||||
new_revision.increase_version 1
|
||||
end
|
||||
|
||||
# The file on disk must be renamed from .tmp to the correct filetype or else Xapian won't know how to index.
|
||||
# Copy file.last_revision.disk_file to new_revision.disk_file
|
||||
new_revision.size = file.last_revision.size
|
||||
new_revision.disk_filename = new_revision.new_storage_filename
|
||||
Rails.logger.info "WebDAV MOVE: Copy file #{file.last_revision.disk_filename} -> #{new_revision.disk_filename}"
|
||||
File.open(file.last_revision.disk_file, 'rb') do |f|
|
||||
new_revision.copy_file_content(f)
|
||||
new_revision.copy_file_content f
|
||||
end
|
||||
|
||||
# Save
|
||||
new_revision.save && resource.file.save
|
||||
|
||||
# Delete (and destroy) the file that should have been renamed and return what should have been returned in case of a copy
|
||||
file.delete(true) ? Created : PreconditionFailed
|
||||
else
|
||||
@ -300,11 +288,10 @@ module RedmineDmsf
|
||||
f = parent.folder
|
||||
end
|
||||
return PreconditionFailed unless exist? && file
|
||||
|
||||
if (project == resource.project) && resource.basename.match(/.\.tmp$/i)
|
||||
Rails.logger.info "WebDAV MOVE: #{file.name} -> #{resource.basename}, possible MSOffice rename to .tmp when saving."
|
||||
# Renaming the file to X.tmp, might be Office that is saving a file. Keep the original file.
|
||||
file.copy_to_filename(resource.project, f, resource.basename)
|
||||
file.copy_to_filename resource.project, f, resource.basename
|
||||
Created
|
||||
else
|
||||
if (project == resource.project) && (file.last_revision.size == 0)
|
||||
@ -313,14 +300,12 @@ module RedmineDmsf
|
||||
else
|
||||
return InternalServerError unless file.move_to(resource.project, f)
|
||||
end
|
||||
|
||||
# Update Revision and names of file [We can link to old physical resource, as it's not changed]
|
||||
if file.last_revision
|
||||
file.last_revision.name = resource.basename
|
||||
file.last_revision.title = DmsfFileRevision.filename_to_title(resource.basename)
|
||||
end
|
||||
file.name = resource.basename
|
||||
|
||||
# Save Changes
|
||||
(file.last_revision.save && file.save) ? Created : PreconditionFailed
|
||||
end
|
||||
|
||||
22
test/fixtures/dmsf_file_revisions.yml
vendored
22
test/fixtures/dmsf_file_revisions.yml
vendored
@ -190,3 +190,25 @@ dmsf_file_revisions_009:
|
||||
dmsf_workflow_assigned_by_user_id: NULL
|
||||
dmsf_workflow_started_by_user_id: NULL
|
||||
created_at: 2017-04-18 14:52:27 +02:00
|
||||
|
||||
dmsf_file_revisions_010:
|
||||
id: 10
|
||||
dmsf_file_id: 5
|
||||
source_dmsf_file_revision_id: NULL
|
||||
name: "test.txt"
|
||||
disk_filename: "test.txt"
|
||||
size: 4
|
||||
mime_type: text/plain
|
||||
title: "Test File"
|
||||
description: 'Some file :-)'
|
||||
workflow: 1 # DmsfWorkflow::STATE_WAITING_FOR_APPROVAL
|
||||
minor_version: 0
|
||||
major_version: 1
|
||||
comment: NULL
|
||||
deleted: 0
|
||||
deleted_by_user_id: NULL
|
||||
user_id: 1
|
||||
dmsf_workflow_assigned_by_user_id: 1
|
||||
dmsf_workflow_started_by_user_id: 1
|
||||
digest: '81dc9bdb52d04dc20036dbd8313ed055'
|
||||
created_at: 2017-04-18 14:52:27 +02:00
|
||||
@ -253,9 +253,10 @@ class DmsfControllerTest < RedmineDmsf::Test::TestCase
|
||||
def test_show_folder_doesnt_correspond_the_project
|
||||
@role.add_permission! :view_dmsf_files
|
||||
@role.add_permission! :view_dmsf_folders
|
||||
# project1 X project2.folder3
|
||||
# Despite the fact that project != @folder3.project
|
||||
assert @project != @folder3.project
|
||||
get :show, params: { id: @project.id, folder_id: @folder3.id }
|
||||
assert_response :not_found
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_new_forbidden
|
||||
|
||||
@ -170,6 +170,12 @@ class DmsfFoldersCopyControllerTest < RedmineDmsf::Test::TestCase
|
||||
assert_nil flash[:error]
|
||||
end
|
||||
|
||||
def test_move_to_another_project
|
||||
post :move, params: { id: @folder1.id, target_project_id: @project2.id, target_folder_id: 'Documents' }
|
||||
assert_response :redirect
|
||||
assert_nil flash[:error]
|
||||
end
|
||||
|
||||
def test_move_the_same_target
|
||||
post :move, params: { id: @folder1.id, target_project_id: @folder1.project.id, target_folder_id: @folder1.dmsf_folder }
|
||||
assert_equal flash[:error], l(:error_target_folder_same)
|
||||
|
||||
@ -322,7 +322,7 @@ class DmsfLinksControllerTest < RedmineDmsf::Test::TestCase
|
||||
type: 'link_to'
|
||||
}}
|
||||
end
|
||||
assert_redirected_to edit_dmsf_path(id: @project1.id, folder_id: @folder1.id)
|
||||
assert_redirected_to dmsf_folder_path(id: @project1, folder_id: @folder1.dmsf_folder)
|
||||
end
|
||||
|
||||
def test_create_folder_link_to_f2
|
||||
@ -337,7 +337,7 @@ class DmsfLinksControllerTest < RedmineDmsf::Test::TestCase
|
||||
type: 'link_to'
|
||||
}}
|
||||
end
|
||||
assert_redirected_to edit_dmsf_path(id: @project1.id, folder_id: @folder1.id)
|
||||
assert_redirected_to dmsf_folder_path(id: @project1, folder_id: @folder1.dmsf_folder)
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
|
||||
@ -37,13 +37,16 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
|
||||
@jsmith_user = User.find_by(login: 'jsmith')
|
||||
@admin_user = User.find_by(login: 'admin')
|
||||
@project1 = Project.find 1
|
||||
@project1.enable_module! :dmsf
|
||||
@project2 = Project.find 2
|
||||
@project2.enable_module! :dmsf
|
||||
@file1 = DmsfFile.find 1
|
||||
@file10 = DmsfFile.find 10
|
||||
@folder1 = DmsfFolder.find 1
|
||||
# Fix permissions for jsmith's role
|
||||
@role = Role.find 1 #
|
||||
@role = Role.find 1
|
||||
@role.add_permission! :view_dmsf_folders
|
||||
@role.add_permission! :folder_manipulation
|
||||
@role.add_permission! :file_manipulation
|
||||
@dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav']
|
||||
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
|
||||
@dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy']
|
||||
@ -68,6 +71,7 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
|
||||
|
||||
def test_truth
|
||||
assert_kind_of Project, @project1
|
||||
assert_kind_of Project, @project2
|
||||
assert_kind_of Role, @role
|
||||
assert_kind_of DmsfFile, @file1
|
||||
assert_kind_of DmsfFile, @file10
|
||||
@ -85,8 +89,8 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
def test_move_to_new_filename_without_folder_manipulation_permission
|
||||
@role.remove_permission! :folder_manipulation
|
||||
def test_move_to_new_filename_without_file_manipulation_permission
|
||||
@role.remove_permission! :file_manipulation
|
||||
new_name = "#{@file1.name}.moved"
|
||||
assert_no_difference '@file1.dmsf_file_revisions.count' do
|
||||
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: nil,
|
||||
@ -95,8 +99,8 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
def test_move_to_new_filename_without_folder_manipulation_permission_as_admin
|
||||
@role.remove_permission! :folder_manipulation
|
||||
def test_move_to_new_filename_without_file_manipulation_permission_as_admin
|
||||
@role.remove_permission! :file_manipulation
|
||||
new_name = "#{@file1.name}.moved"
|
||||
assert_difference '@file1.dmsf_file_revisions.count', +1 do
|
||||
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: nil,
|
||||
@ -107,6 +111,37 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
def test_without_folder_manipulation_permission
|
||||
@role.remove_permission! :folder_manipulation
|
||||
new_name = "#{@folder1.title}.moved"
|
||||
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", params: nil,
|
||||
headers: @jsmith.merge!({ destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" })
|
||||
assert_response :forbidden
|
||||
end
|
||||
|
||||
def test_without_folder_manipulation_permission_as_admin
|
||||
@role.remove_permission! :folder_manipulation
|
||||
new_name = "#{@folder1.title}.moved"
|
||||
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", params: nil,
|
||||
headers: @admin.merge!({ destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" })
|
||||
assert_response :created
|
||||
end
|
||||
|
||||
def test_move_folder_to_another_project
|
||||
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", params: nil,
|
||||
headers: @admin.merge!({ destination: "http://www.example.com/dmsf/webdav/#{@project2.identifier}/#{@folder1.title}" })
|
||||
assert_response :created
|
||||
@folder1.dmsf_folders.each do |d|
|
||||
assert_equal @project2, d.project
|
||||
end
|
||||
@folder1.dmsf_files.each do |f|
|
||||
assert_equal @project2, f.project
|
||||
end
|
||||
@folder1.dmsf_links.each do |l|
|
||||
assert_equal @project2, l.project
|
||||
end
|
||||
end
|
||||
|
||||
def test_move_non_existent_file
|
||||
process :move, "/dmsf/webdav/#{@project1.identifier}/not_a_file.txt", params: nil,
|
||||
headers: @jsmith.merge!({ destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/moved_file.txt" })
|
||||
|
||||
@ -27,8 +27,10 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
|
||||
:dmsf_folder_permissions
|
||||
|
||||
def setup
|
||||
@project = Project.find 1
|
||||
@project.enable_module! :dmsf
|
||||
@project1 = Project.find 1
|
||||
@project1.enable_module! :dmsf
|
||||
@project2 = Project.find 2
|
||||
@project2.enable_module! :dmsf
|
||||
@folder1 = DmsfFolder.find 1
|
||||
@folder2 = DmsfFolder.find 2
|
||||
@folder4 = DmsfFolder.find 4
|
||||
@ -51,7 +53,8 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
|
||||
assert_kind_of DmsfFolder, @folder5
|
||||
assert_kind_of DmsfFolder, @folder6
|
||||
assert_kind_of DmsfFolder, @folder7
|
||||
assert_kind_of Project, @project
|
||||
assert_kind_of Project, @project1
|
||||
assert_kind_of Project, @project2
|
||||
assert_kind_of User, @manager
|
||||
assert_kind_of User, @developer
|
||||
assert_kind_of Role, @manager_role
|
||||
@ -69,7 +72,7 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
|
||||
assert_equal 4, DmsfFolder.visible.where(project_id: 1).all.size
|
||||
# Anonymous user
|
||||
User.current = User.anonymous
|
||||
@project.add_default_member User.anonymous
|
||||
@project1.add_default_member User.anonymous
|
||||
assert_equal 5, DmsfFolder.visible.where(project_id: 1).all.size
|
||||
end
|
||||
|
||||
@ -145,7 +148,7 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
|
||||
end
|
||||
|
||||
def test_directory_tree
|
||||
tree = DmsfFolder.directory_tree(@project)
|
||||
tree = DmsfFolder.directory_tree(@project1)
|
||||
assert tree
|
||||
# [["Documents", nil],
|
||||
# ["...folder7", 7],
|
||||
@ -157,7 +160,7 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
|
||||
end
|
||||
|
||||
def test_directory_tree_id
|
||||
tree = DmsfFolder.directory_tree(@project.id)
|
||||
tree = DmsfFolder.directory_tree(@project1.id)
|
||||
assert tree
|
||||
# [["Documents", nil],
|
||||
# ["...folder7", 7],
|
||||
@ -193,4 +196,23 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
|
||||
assert_equal 1, users.size
|
||||
end
|
||||
|
||||
def test_move_to
|
||||
assert @folder1.move_to(@project2, nil)
|
||||
assert_equal @project2, @folder1.project
|
||||
@folder1.dmsf_folders.each do |d|
|
||||
assert_equal @project2, d.project
|
||||
end
|
||||
@folder1.dmsf_files.each do |f|
|
||||
assert_equal @project2, f.project
|
||||
end
|
||||
@folder1.dmsf_links.each do |l|
|
||||
assert_equal @project2, l.project
|
||||
end
|
||||
end
|
||||
|
||||
def test_copy_to
|
||||
assert @folder1.copy_to(@project2, nil)
|
||||
assert DmsfFolder.find_by_title(@project2, nil, @folder1.title)
|
||||
end
|
||||
|
||||
end
|
||||
@ -163,8 +163,8 @@ class DmsfLinksTest < RedmineDmsf::Test::UnitTest
|
||||
end
|
||||
|
||||
def test_folder
|
||||
assert_equal @folder1, @file_link.folder
|
||||
assert_nil @folder_link.folder
|
||||
assert_equal @folder1, @file_link.dmsf_folder
|
||||
assert_nil @folder_link.dmsf_folder
|
||||
end
|
||||
|
||||
def test_title
|
||||
@ -174,7 +174,7 @@ class DmsfLinksTest < RedmineDmsf::Test::UnitTest
|
||||
|
||||
def test_find_link_by_file_name
|
||||
file_link = DmsfLink.find_link_by_file_name(@file_link.project,
|
||||
@file_link.folder, @file_link.target_file.name)
|
||||
@file_link.dmsf_folder, @file_link.target_file.name)
|
||||
assert file_link, 'File link not found by its name'
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user