#1132 Copying/Moving of multiple entries
This commit is contained in:
parent
17ac75f90a
commit
06d7bb8762
@ -111,4 +111,3 @@ Style/OpenStructUse:
|
|||||||
Style/OptionalBooleanParameter:
|
Style/OptionalBooleanParameter:
|
||||||
Exclude:
|
Exclude:
|
||||||
- lib/redmine_dmsf/field_formats/dmsf_file_format.rb
|
- lib/redmine_dmsf/field_formats/dmsf_file_format.rb
|
||||||
|
|
||||||
@ -61,8 +61,8 @@ def dmsf_init
|
|||||||
|
|
||||||
Redmine::AccessControl.map do |map|
|
Redmine::AccessControl.map do |map|
|
||||||
map.project_module :dmsf do |pmap|
|
map.project_module :dmsf do |pmap|
|
||||||
pmap.permission :view_dmsf_file_revision_accesses, read: true
|
pmap.permission :view_dmsf_file_revision_accesses, {}, read: true
|
||||||
pmap.permission :view_dmsf_file_revisions, read: true
|
pmap.permission :view_dmsf_file_revisions, {}, read: true
|
||||||
pmap.permission :view_dmsf_folders, { dmsf: %i[show index] }, read: true
|
pmap.permission :view_dmsf_folders, { dmsf: %i[show index] }, read: true
|
||||||
pmap.permission :user_preferences, { dmsf_state: [:user_pref_save] }, require: :member
|
pmap.permission :user_preferences, { dmsf_state: [:user_pref_save] }, require: :member
|
||||||
pmap.permission(:view_dmsf_files,
|
pmap.permission(:view_dmsf_files,
|
||||||
@ -75,9 +75,8 @@ def dmsf_init
|
|||||||
{ dmsf_public_urls: [:create] }
|
{ dmsf_public_urls: [:create] }
|
||||||
pmap.permission :folder_manipulation,
|
pmap.permission :folder_manipulation,
|
||||||
{ dmsf: %i[new create delete edit save edit_root save_root lock unlock notify_activate
|
{ dmsf: %i[new create delete edit save edit_root save_root lock unlock notify_activate
|
||||||
notify_deactivate restore drop],
|
notify_deactivate restore drop copymove],
|
||||||
dmsf_folder_permissions: %i[new append autocomplete_for_user],
|
dmsf_folder_permissions: %i[new append autocomplete_for_user],
|
||||||
dmsf_folders_copy: %i[new copy move],
|
|
||||||
dmsf_context_menus: [:dmsf] }
|
dmsf_context_menus: [:dmsf] }
|
||||||
pmap.permission :file_manipulation,
|
pmap.permission :file_manipulation,
|
||||||
{ dmsf_files: %i[create_revision lock unlock delete_revision obsolete_revision
|
{ dmsf_files: %i[create_revision lock unlock delete_revision obsolete_revision
|
||||||
@ -85,7 +84,6 @@ def dmsf_init
|
|||||||
dmsf_upload: %i[upload_files upload commit_files commit delete_dmsf_attachment
|
dmsf_upload: %i[upload_files upload commit_files commit delete_dmsf_attachment
|
||||||
delete_dmsf_link_attachment multi_upload],
|
delete_dmsf_link_attachment multi_upload],
|
||||||
dmsf_links: %i[new create destroy restore autocomplete_for_project autocomplete_for_folder],
|
dmsf_links: %i[new create destroy restore autocomplete_for_project autocomplete_for_folder],
|
||||||
dmsf_files_copy: %i[new copy move],
|
|
||||||
dmsf_context_menus: [:dmsf] }
|
dmsf_context_menus: [:dmsf] }
|
||||||
pmap.permission :file_delete,
|
pmap.permission :file_delete,
|
||||||
{ dmsf: %i[trash delete_entries empty_trash],
|
{ dmsf: %i[trash delete_entries empty_trash],
|
||||||
@ -97,8 +95,7 @@ def dmsf_init
|
|||||||
pmap.permission :manage_workflows,
|
pmap.permission :manage_workflows,
|
||||||
{ dmsf_workflows: %i[index new create destroy show new_step add_step remove_step
|
{ dmsf_workflows: %i[index new create destroy show new_step add_step remove_step
|
||||||
reorder_steps update update_step delete_step edit] }
|
reorder_steps update update_step delete_step edit] }
|
||||||
pmap.permission :display_system_folders,
|
pmap.permission :display_system_folders, {}, read: true
|
||||||
read: true
|
|
||||||
# Watchers
|
# Watchers
|
||||||
pmap.permission :view_dmsf_file_watchers, {}, read: true
|
pmap.permission :view_dmsf_file_watchers, {}, read: true
|
||||||
pmap.permission :add_dmsf_file_watchers, { watchers: %i[new create append autocomplete_for_user] }
|
pmap.permission :add_dmsf_file_watchers, { watchers: %i[new create append autocomplete_for_user] }
|
||||||
|
|||||||
@ -35,6 +35,8 @@ class DmsfController < ApplicationController
|
|||||||
before_action :find_folder_by_title, only: [:show]
|
before_action :find_folder_by_title, only: [:show]
|
||||||
before_action :query, only: %i[expand_folder show trash empty_trash index]
|
before_action :query, only: %i[expand_folder show trash empty_trash index]
|
||||||
before_action :project_roles, only: %i[new edit create save]
|
before_action :project_roles, only: %i[new edit create save]
|
||||||
|
before_action :find_target_folder, only: %i[copymove entries_operation]
|
||||||
|
before_action :check_target_folder, only: [:entries_operation]
|
||||||
|
|
||||||
accept_api_auth :show, :create, :save, :delete
|
accept_api_auth :show, :create, :save, :delete
|
||||||
|
|
||||||
@ -138,59 +140,55 @@ class DmsfController < ApplicationController
|
|||||||
flash[:error] = e.message
|
flash[:error] = e.message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def copymove
|
||||||
|
@ids = params[:ids]
|
||||||
|
member = Member.find_by(project_id: @project.id, user_id: User.current.id)
|
||||||
|
@fast_links = member&.dmsf_fast_links
|
||||||
|
unless @fast_links
|
||||||
|
@projects = DmsfFolder.allowed_target_projects_on_copy
|
||||||
|
@folders = DmsfFolder.directory_tree(@target_project, @folder)
|
||||||
|
@target_folder = DmsfFolder.visible.find(params[:target_folder_id]) if params[:target_folder_id].present?
|
||||||
|
end
|
||||||
|
@back_url = params[:back_url]
|
||||||
|
render layout: !request.xhr?
|
||||||
|
end
|
||||||
|
|
||||||
def entries_operation
|
def entries_operation
|
||||||
# Download/Email
|
# Download/Email
|
||||||
if params[:ids].present?
|
if @selected_folders.blank? && @selected_files.blank? && @selected_links.blank?
|
||||||
selected_folders = params[:ids].grep(/folder-\d+/).map { |x| Regexp.last_match(1).to_i if x =~ /folder-(\d+)/ }
|
|
||||||
selected_files = params[:ids].grep(/file-\d+/).map { |x| Regexp.last_match(1).to_i if x =~ /file-(\d+)/ }
|
|
||||||
selected_dir_links = params[:ids].grep(/folder-link-\d+/)
|
|
||||||
.map { |x| Regexp.last_match(1).to_i if x =~ /folder-link-(\d+)/ }
|
|
||||||
selected_file_links = params[:ids].grep(/file-link-\d+/)
|
|
||||||
.map { |x| Regexp.last_match(1).to_i if x =~ /file-link-(\d+)/ }
|
|
||||||
selected_url_links = params[:ids].grep(/url-link-\d+/)
|
|
||||||
.map { |x| Regexp.last_match(1).to_i if x =~ /url-link-(\d+)/ }
|
|
||||||
else
|
|
||||||
selected_folders = []
|
|
||||||
selected_files = []
|
|
||||||
selected_dir_links = []
|
|
||||||
selected_file_links = []
|
|
||||||
selected_url_links = []
|
|
||||||
end
|
|
||||||
|
|
||||||
if selected_folders.blank? &&
|
|
||||||
selected_files.blank? &&
|
|
||||||
selected_dir_links.blank? &&
|
|
||||||
selected_file_links.blank? &&
|
|
||||||
selected_url_links.blank?
|
|
||||||
flash[:warning] = l(:warning_no_entries_selected)
|
flash[:warning] = l(:warning_no_entries_selected)
|
||||||
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if selected_dir_links.present? && (params[:email_entries].present? || params[:download_entries].present?)
|
if @selected_dir_links.present? && (params[:email_entries].present? || params[:download_entries].present?)
|
||||||
selected_folders = DmsfLink.where(id: selected_dir_links).pluck(:target_id) | selected_folders
|
@selected_folders = DmsfLink.where(id: selected_dir_links).pluck(:target_id) | @selected_folders
|
||||||
end
|
end
|
||||||
|
|
||||||
if selected_file_links.present? && (params[:email_entries].present? || params[:download_entries].present?)
|
if @selected_file_links.present? && (params[:email_entries].present? || params[:download_entries].present?)
|
||||||
selected_files = DmsfLink.where(id: selected_file_links).pluck(:target_id) | selected_files
|
@selected_files = DmsfLink.where(id: selected_file_links).pluck(:target_id) | @selected_files
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if params[:email_entries].present?
|
if params[:email_entries].present?
|
||||||
email_entries selected_folders, selected_files
|
email_entries @selected_folders, @selected_files
|
||||||
elsif params[:restore_entries].present?
|
elsif params[:restore_entries].present?
|
||||||
restore_entries selected_folders, selected_files, selected_dir_links, selected_file_links, selected_url_links
|
restore_entries @selected_folders, @selected_files, @selected_links
|
||||||
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
||||||
elsif params[:delete_entries].present?
|
elsif params[:delete_entries].present?
|
||||||
delete_entries(selected_folders, selected_files, selected_dir_links, selected_file_links, selected_url_links,
|
delete_entries @selected_folders, @selected_files, @selected_links, false
|
||||||
false)
|
|
||||||
redirect_back_or_default dmsf_folder_path id: @project, folder_id: @folder
|
redirect_back_or_default dmsf_folder_path id: @project, folder_id: @folder
|
||||||
elsif params[:destroy_entries].present?
|
elsif params[:destroy_entries].present?
|
||||||
delete_entries(selected_folders, selected_files, selected_dir_links, selected_file_links, selected_url_links,
|
delete_entries @selected_folders, @selected_files, @selected_links, true
|
||||||
true)
|
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
||||||
|
elsif params[:move_entries].present?
|
||||||
|
move_entries @selected_folders, @selected_files, @selected_links
|
||||||
|
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
||||||
|
elsif params[:copy_entries].present?
|
||||||
|
copy_entries @selected_folders, @selected_files, @selected_links
|
||||||
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
||||||
else
|
else
|
||||||
download_entries selected_folders, selected_files
|
download_entries @selected_folders, @selected_files
|
||||||
end
|
end
|
||||||
rescue RedmineDmsf::Errors::DmsfFileNotFoundError
|
rescue RedmineDmsf::Errors::DmsfFileNotFoundError
|
||||||
render_404
|
render_404
|
||||||
@ -574,7 +572,7 @@ class DmsfController < ApplicationController
|
|||||||
zip
|
zip
|
||||||
end
|
end
|
||||||
|
|
||||||
def restore_entries(selected_folders, selected_files, selected_dir_links, selected_file_links, selected_url_links)
|
def restore_entries(selected_folders, selected_files, selected_links)
|
||||||
# Folders
|
# Folders
|
||||||
selected_folders.each do |id|
|
selected_folders.each do |id|
|
||||||
folder = DmsfFolder.find_by(id: id)
|
folder = DmsfFolder.find_by(id: id)
|
||||||
@ -589,7 +587,7 @@ class DmsfController < ApplicationController
|
|||||||
flash[:error] = file.errors.full_messages.to_sentence unless file.restore
|
flash[:error] = file.errors.full_messages.to_sentence unless file.restore
|
||||||
end
|
end
|
||||||
# Links
|
# Links
|
||||||
(selected_dir_links + selected_file_links + selected_url_links).each do |id|
|
selected_links.each do |id|
|
||||||
link = DmsfLink.find_by(id: id)
|
link = DmsfLink.find_by(id: id)
|
||||||
raise RedmineDmsf::Errors::DmsfFileNotFoundError unless link
|
raise RedmineDmsf::Errors::DmsfFileNotFoundError unless link
|
||||||
|
|
||||||
@ -597,8 +595,7 @@ class DmsfController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_entries(selected_folders, selected_files, selected_dir_links, selected_file_links, selected_url_links,
|
def delete_entries(selected_folders, selected_files, selected_links, commit)
|
||||||
commit)
|
|
||||||
# Folders
|
# Folders
|
||||||
selected_folders.each do |id|
|
selected_folders.each do |id|
|
||||||
raise RedmineDmsf::Errors::DmsfAccessError unless User.current.allowed_to?(:folder_manipulation, @project)
|
raise RedmineDmsf::Errors::DmsfAccessError unless User.current.allowed_to?(:folder_manipulation, @project)
|
||||||
@ -613,9 +610,10 @@ class DmsfController < ApplicationController
|
|||||||
# Files
|
# Files
|
||||||
deleted_files = []
|
deleted_files = []
|
||||||
not_deleted_files = []
|
not_deleted_files = []
|
||||||
selected_files.each do |id|
|
if selected_files.any?
|
||||||
raise RedmineDmsf::Errors::DmsfAccessError unless User.current.allowed_to?(:file_delete, @project)
|
raise RedmineDmsf::Errors::DmsfAccessError unless User.current.allowed_to?(:file_delete, @project)
|
||||||
|
end
|
||||||
|
selected_files.each do |id|
|
||||||
file = DmsfFile.find_by(id: id)
|
file = DmsfFile.find_by(id: id)
|
||||||
if file
|
if file
|
||||||
if file.delete(commit: commit)
|
if file.delete(commit: commit)
|
||||||
@ -647,21 +645,70 @@ class DmsfController < ApplicationController
|
|||||||
flash[:warning] = l(:warning_some_entries_were_not_deleted, entries: not_deleted_files.map(&:title).join(', '))
|
flash[:warning] = l(:warning_some_entries_were_not_deleted, entries: not_deleted_files.map(&:title).join(', '))
|
||||||
end
|
end
|
||||||
# Links
|
# Links
|
||||||
selected_dir_links.each do |id|
|
if selected_links.any?
|
||||||
raise RedmineDmsf::Errors::DmsfAccessError unless User.current.allowed_to?(:folder_manipulation, @project)
|
raise RedmineDmsf::Errors::DmsfAccessError unless User.current.allowed_to?(:folder_manipulation, @project)
|
||||||
|
|
||||||
link = DmsfLink.find_by(id: id)
|
|
||||||
link&.delete commit: commit
|
|
||||||
end
|
end
|
||||||
(selected_file_links + selected_url_links).each do |id|
|
selected_links.each do |id|
|
||||||
raise RedmineDmsf::Errors::DmsfAccessError unless User.current.allowed_to?(:file_delete, @project)
|
|
||||||
|
|
||||||
link = DmsfLink.find_by(id: id)
|
link = DmsfLink.find_by(id: id)
|
||||||
link&.delete commit: commit
|
link&.delete commit: commit
|
||||||
end
|
end
|
||||||
flash[:notice] = l(:notice_entries_deleted) if flash[:error].blank? && flash[:warning].blank?
|
flash[:notice] = l(:notice_entries_deleted) if flash[:error].blank? && flash[:warning].blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def copy_entries(selected_folders, selected_files, selected_links)
|
||||||
|
# Folders
|
||||||
|
selected_folders.each do |id|
|
||||||
|
folder = DmsfFolder.find_by(id: id)
|
||||||
|
new_folder = folder.copy_to(@target_project, @target_folder)
|
||||||
|
raise(StandardError, new_folder.errors.full_messages.to_sentence) unless new_folder.errors.empty?
|
||||||
|
end
|
||||||
|
# Files
|
||||||
|
selected_files.each do |id|
|
||||||
|
file = DmsfFile.find_by(id: id)
|
||||||
|
new_file = file.copy_to(@target_project, @target_folder)
|
||||||
|
raise(StandardError, new_file.errors.full_messages.to_sentence) unless new_file.errors.empty?
|
||||||
|
end
|
||||||
|
# Links
|
||||||
|
selected_links.each do |id|
|
||||||
|
link = DmsfLink.find_by(id: id)
|
||||||
|
new_link = link.copy_to(@target_project, @target_folder)
|
||||||
|
raise(StandardError, new_link.errors.full_messages.to_sentence) unless new_link.errors.empty?
|
||||||
|
end
|
||||||
|
flash[:notice] = l(:notice_entries_copied) if flash[:error].blank? && flash[:warning].blank?
|
||||||
|
end
|
||||||
|
|
||||||
|
def move_entries(selected_folders, selected_files, selected_links)
|
||||||
|
# Permissions
|
||||||
|
if selected_folders.any? && !User.current.allowed_to?(:folder_manipulation, @project)
|
||||||
|
raise RedmineDmsf::Errors::DmsfAccessError
|
||||||
|
end
|
||||||
|
if (selected_folders.any? || selected_links.any?) && !User.current.allowed_to?(:file_manipulation, @project)
|
||||||
|
raise RedmineDmsf::Errors::DmsfAccessError
|
||||||
|
end
|
||||||
|
# Folders
|
||||||
|
selected_folders.each do |id|
|
||||||
|
folder = DmsfFolder.find_by(id: id)
|
||||||
|
unless folder.move_to(@target_project, @target_folder)
|
||||||
|
raise(StandardError, folder.errors.full_messages.to_sentence)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Files
|
||||||
|
selected_files.each do |id|
|
||||||
|
file = DmsfFile.find_by(id: id)
|
||||||
|
unless file.move_to(@target_project, @target_folder)
|
||||||
|
raise(StandardError, file.errors.full_messages.to_sentence)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Links
|
||||||
|
selected_links.each do |id|
|
||||||
|
link = DmsfLink.find_by(id: id)
|
||||||
|
unless link.move_to(@target_project, @target_folder)
|
||||||
|
raise(StandardError, link.errors.full_messages.to_sentence)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
flash[:notice] = l(:notice_entries_moved) if flash[:error].blank? && flash[:warning].blank?
|
||||||
|
end
|
||||||
|
|
||||||
def find_folder
|
def find_folder
|
||||||
@folder = DmsfFolder.find(params[:folder_id]) if params[:folder_id].present?
|
@folder = DmsfFolder.find(params[:folder_id]) if params[:folder_id].present?
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
@ -719,4 +766,68 @@ class DmsfController < ApplicationController
|
|||||||
@project_roles = Role.givable.joins(:member_roles).joins(:members).where(members: { project_id: @project.id })
|
@project_roles = Role.givable.joins(:member_roles).joins(:members).where(members: { project_id: @project.id })
|
||||||
.distinct
|
.distinct
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_target_folder
|
||||||
|
@target_project = if params[:dmsf_entries] && params[:dmsf_entries][:target_project_id].present?
|
||||||
|
Project.find params[:dmsf_entries][:target_project_id]
|
||||||
|
else
|
||||||
|
@project
|
||||||
|
end
|
||||||
|
if params[:dmsf_entries] && params[:dmsf_entries][:target_folder_id].present?
|
||||||
|
target_folder_id = params[:dmsf_entries][:target_folder_id]
|
||||||
|
@target_folder = DmsfFolder.find(target_folder_id)
|
||||||
|
raise ActiveRecord::RecordNotFound unless DmsfFolder.visible.exists?(id: target_folder_id)
|
||||||
|
|
||||||
|
@target_project = @target_folder&.project
|
||||||
|
end
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render_404
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_target_folder
|
||||||
|
if params[:ids].present?
|
||||||
|
@selected_folders = params[:ids].grep(/folder-\d+/).map { |x| Regexp.last_match(1).to_i if x =~ /folder-(\d+)/ }
|
||||||
|
@selected_files = params[:ids].grep(/file-\d+/).map { |x| Regexp.last_match(1).to_i if x =~ /file-(\d+)/ }
|
||||||
|
@selected_dir_links = params[:ids].grep(/folder-link-\d+/)
|
||||||
|
.map { |x| Regexp.last_match(1).to_i if x =~ /folder-link-(\d+)/ }
|
||||||
|
@selected_file_links = params[:ids].grep(/file-link-\d+/)
|
||||||
|
.map { |x| Regexp.last_match(1).to_i if x =~ /file-link-(\d+)/ }
|
||||||
|
@selected_url_links = params[:ids].grep(/url-link-\d+/)
|
||||||
|
.map { |x| Regexp.last_match(1).to_i if x =~ /url-link-(\d+)/ }
|
||||||
|
@selected_links = @selected_dir_links + @selected_file_links + @selected_url_links
|
||||||
|
else
|
||||||
|
@selected_folders = []
|
||||||
|
@selected_files = []
|
||||||
|
@selected_links = []
|
||||||
|
end
|
||||||
|
if params[:copy_entries].present? || params[:move_entries].present?
|
||||||
|
begin
|
||||||
|
# Prevent copying/moving to the same destination
|
||||||
|
folders = DmsfFolder.where(id: @selected_folders).to_a
|
||||||
|
files = DmsfFile.where(id: @selected_files).to_a
|
||||||
|
links = DmsfLink.where(id: @selected_links).to_a
|
||||||
|
(folders + files + links).each do |entry|
|
||||||
|
raise RedmineDmsf::Errors::DmsfParentError if entry.dmsf_folder == @target_folder || entry == @target_folder
|
||||||
|
end
|
||||||
|
# Prevent recursion
|
||||||
|
if params[:move_entries].present?
|
||||||
|
folders.each do |entry|
|
||||||
|
b = entry.any_child?(@target_folder)
|
||||||
|
raise RedmineDmsf::Errors::DmsfParentError if entry.any_child?(@target_folder)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Check permissions
|
||||||
|
if (@target_folder && (@target_folder.locked_for_user? ||
|
||||||
|
!DmsfFolder.permissions?(@target_folder, allow_system: false))) ||
|
||||||
|
!@target_project.allows_to?(:folder_manipulation)
|
||||||
|
raise RedmineDmsf::Errors::DmsfAccessError
|
||||||
|
end
|
||||||
|
rescue RedmineDmsf::Errors::DmsfParentError
|
||||||
|
flash[:error] = l(:error_target_folder_same)
|
||||||
|
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder)
|
||||||
|
rescue RedmineDmsf::Errors::DmsfAccessError
|
||||||
|
render_403
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,138 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# Redmine plugin for Document Management System "Features"
|
|
||||||
#
|
|
||||||
# Copyright © 2011 Vít Jonáš <vit.jonas@gmail.com>
|
|
||||||
# Copyright © 2011-23 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.
|
|
||||||
|
|
||||||
# Files copy controller
|
|
||||||
class DmsfFilesCopyController < ApplicationController
|
|
||||||
menu_item :dmsf
|
|
||||||
|
|
||||||
before_action :find_file
|
|
||||||
before_action :authorize
|
|
||||||
before_action :find_target_folder
|
|
||||||
before_action :check_target_folder, only: %i[copy move]
|
|
||||||
|
|
||||||
accept_api_auth :copy, :move
|
|
||||||
|
|
||||||
helper :dmsf
|
|
||||||
|
|
||||||
def new
|
|
||||||
member = Member.find_by(project_id: @project.id, user_id: User.current.id)
|
|
||||||
@fast_links = member&.dmsf_fast_links
|
|
||||||
unless @fast_links
|
|
||||||
@projects = DmsfFile.allowed_target_projects_on_copy
|
|
||||||
@folders = DmsfFolder.directory_tree(@target_project, @folder)
|
|
||||||
end
|
|
||||||
@back_url = params[:back_url]
|
|
||||||
render layout: !request.xhr?
|
|
||||||
end
|
|
||||||
|
|
||||||
def copy
|
|
||||||
new_file = @file.copy_to(@target_project, @target_folder)
|
|
||||||
failure = new_file.nil? || new_file.errors.present?
|
|
||||||
if failure
|
|
||||||
flash[:error] = new_file ? new_file.errors.full_messages.to_sentence : @file.errors.full_messages.to_sentence
|
|
||||||
else
|
|
||||||
flash[:notice] = l(:notice_successful_update)
|
|
||||||
end
|
|
||||||
respond_to do |format|
|
|
||||||
format.html do
|
|
||||||
redirect_back_or_default dmsf_folder_path(id: @file.project, folder_id: @file.dmsf_folder)
|
|
||||||
end
|
|
||||||
format.api do
|
|
||||||
if failure
|
|
||||||
render_validation_errors new_file || @file
|
|
||||||
else
|
|
||||||
render_api_ok
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def move
|
|
||||||
success = @file.move_to(@target_project, @target_folder)
|
|
||||||
if success
|
|
||||||
flash[:notice] = l(:notice_successful_update)
|
|
||||||
else
|
|
||||||
flash[:error] = @file.errors.full_messages.to_sentence
|
|
||||||
end
|
|
||||||
respond_to do |format|
|
|
||||||
format.html do
|
|
||||||
redirect_back_or_default dmsf_folder_path(id: @file.project, folder_id: @file.dmsf_folder)
|
|
||||||
end
|
|
||||||
format.api do
|
|
||||||
if success
|
|
||||||
render_api_ok
|
|
||||||
else
|
|
||||||
render_validation_errors @file
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def find_file
|
|
||||||
raise ActiveRecord::RecordNotFound unless DmsfFile.exists?(id: params[:id])
|
|
||||||
|
|
||||||
@file = DmsfFile.visible.find params[:id]
|
|
||||||
raise RedmineDmsf::Errors::DmsfAccessError if @file.locked_for_user?
|
|
||||||
|
|
||||||
@project = @file.project
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
rescue RedmineDmsf::Errors::DmsfAccessError
|
|
||||||
render_403
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_target_folder
|
|
||||||
target_folder_id = if params[:target_folder_id].present?
|
|
||||||
params[:target_folder_id]
|
|
||||||
elsif params[:dmsf_file_or_folder] && params[:dmsf_file_or_folder][:target_folder_id].present?
|
|
||||||
params[:dmsf_file_or_folder][:target_folder_id]
|
|
||||||
end
|
|
||||||
@target_folder = DmsfFolder.visible.find(target_folder_id) if target_folder_id
|
|
||||||
target_project_id = if params[:target_project_id].present?
|
|
||||||
params[:target_project_id]
|
|
||||||
elsif params[:dmsf_file_or_folder] && params[:dmsf_file_or_folder][:target_project_id].present?
|
|
||||||
params[:dmsf_file_or_folder][:target_project_id]
|
|
||||||
else
|
|
||||||
@target_folder&.project_id
|
|
||||||
end
|
|
||||||
@target_project = target_project_id ? Project.visible.find(target_project_id) : @project
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_target_folder
|
|
||||||
if (@target_folder && @target_folder == @file.dmsf_folder) ||
|
|
||||||
(@target_folder.nil? && @file.dmsf_folder.nil? && @target_project == @file.project)
|
|
||||||
flash[:error] = l(:error_target_folder_same)
|
|
||||||
redirect_to action: :new, id: @file, target_project_id: @target_project&.id, target_folder_id: @target_folder
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if (@target_folder && (@target_folder.locked_for_user? ||
|
|
||||||
!DmsfFolder.permissions?(@target_folder, allow_system: false))) ||
|
|
||||||
!@target_project.allows_to?(:file_manipulation)
|
|
||||||
raise RedmineDmsf::Errors::DmsfAccessError
|
|
||||||
end
|
|
||||||
rescue RedmineDmsf::Errors::DmsfAccessError
|
|
||||||
render_403
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,137 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# Redmine plugin for Document Management System "Features"
|
|
||||||
#
|
|
||||||
# Copyright © 2011 Vít Jonáš <vit.jonas@gmail.com>
|
|
||||||
# Copyright © 2011-23 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.
|
|
||||||
|
|
||||||
# Folders copy controller
|
|
||||||
class DmsfFoldersCopyController < ApplicationController
|
|
||||||
menu_item :dmsf
|
|
||||||
|
|
||||||
before_action :find_folder
|
|
||||||
before_action :authorize
|
|
||||||
before_action :find_target_folder
|
|
||||||
before_action :check_target_folder, only: %i[copy move]
|
|
||||||
|
|
||||||
accept_api_auth :copy, :move
|
|
||||||
|
|
||||||
helper :dmsf
|
|
||||||
|
|
||||||
def new
|
|
||||||
member = Member.find_by(project_id: @project.id, user_id: User.current.id)
|
|
||||||
@fast_links = member&.dmsf_fast_links
|
|
||||||
unless @fast_links
|
|
||||||
@projects = DmsfFolder.allowed_target_projects_on_copy
|
|
||||||
@folders = DmsfFolder.directory_tree(@target_project, @folder)
|
|
||||||
@target_folder = DmsfFolder.visible.find(params[:target_folder_id]) if params[:target_folder_id].present?
|
|
||||||
end
|
|
||||||
@back_url = params[:back_url]
|
|
||||||
render layout: !request.xhr?
|
|
||||||
end
|
|
||||||
|
|
||||||
def copy
|
|
||||||
new_folder = @folder.copy_to(@target_project, @target_folder)
|
|
||||||
success = new_folder.errors.empty?
|
|
||||||
if success
|
|
||||||
flash[:notice] = l(:notice_successful_update)
|
|
||||||
else
|
|
||||||
flash[:error] = new_folder.errors.full_messages.to_sentence
|
|
||||||
end
|
|
||||||
respond_to do |format|
|
|
||||||
format.html do
|
|
||||||
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder.dmsf_folder)
|
|
||||||
end
|
|
||||||
format.api do
|
|
||||||
if success
|
|
||||||
render_api_ok
|
|
||||||
else
|
|
||||||
render_validation_errors new_folder
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def move
|
|
||||||
success = @folder.move_to(@target_project, @target_folder)
|
|
||||||
if success
|
|
||||||
flash[:notice] = l(:notice_successful_update)
|
|
||||||
else
|
|
||||||
flash[:error] = @folder.errors.full_messages.to_sentence
|
|
||||||
end
|
|
||||||
respond_to do |format|
|
|
||||||
format.html do
|
|
||||||
redirect_back_or_default dmsf_folder_path(id: @project, folder_id: @folder.dmsf_folder)
|
|
||||||
end
|
|
||||||
format.api do
|
|
||||||
if success
|
|
||||||
render_api_ok
|
|
||||||
else
|
|
||||||
render_validation_errors @folder
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def find_folder
|
|
||||||
raise ActiveRecord::RecordNotFound unless DmsfFolder.exists?(id: params[:id])
|
|
||||||
|
|
||||||
@folder = DmsfFolder.visible.find params[:id]
|
|
||||||
raise RedmineDmsf::Errors::DmsfAccessError if @folder.locked_for_user?
|
|
||||||
|
|
||||||
@project = @folder.project
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
rescue RedmineDmsf::Errors::DmsfAccessError
|
|
||||||
render_403
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_target_folder
|
|
||||||
@target_project = if params[:dmsf_file_or_folder] && params[:dmsf_file_or_folder][:target_project_id].present?
|
|
||||||
Project.find params[:dmsf_file_or_folder][:target_project_id]
|
|
||||||
else
|
|
||||||
@project
|
|
||||||
end
|
|
||||||
if params[:dmsf_file_or_folder] && params[:dmsf_file_or_folder][:target_folder_id].present?
|
|
||||||
target_folder_id = params[:dmsf_file_or_folder][:target_folder_id]
|
|
||||||
@target_folder = DmsfFolder.find(target_folder_id)
|
|
||||||
raise ActiveRecord::RecordNotFound unless DmsfFolder.visible.exists?(id: target_folder_id)
|
|
||||||
|
|
||||||
@target_project = @target_folder&.project
|
|
||||||
end
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_target_folder
|
|
||||||
if (@target_folder && @target_folder == @folder.dmsf_folder) ||
|
|
||||||
(@target_folder.nil? && @folder.dmsf_folder.nil? && @target_project == @folder.project)
|
|
||||||
flash[:error] = l(:error_target_folder_same)
|
|
||||||
redirect_to action: :new, id: @folder, target_project_id: @target_project.id, target_folder_id: @target_folder
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if (@target_folder && (@target_folder.locked_for_user? ||
|
|
||||||
!DmsfFolder.permissions?(@target_folder, allow_system: false))) ||
|
|
||||||
!@target_project.allows_to?(:folder_manipulation)
|
|
||||||
raise RedmineDmsf::Errors::DmsfAccessError
|
|
||||||
end
|
|
||||||
rescue RedmineDmsf::Errors::DmsfAccessError
|
|
||||||
render_403
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -304,12 +304,11 @@ class DmsfFolder < ApplicationRecord
|
|||||||
new_folder.description = description
|
new_folder.description = description
|
||||||
new_folder.user = User.current
|
new_folder.user = User.current
|
||||||
new_folder.custom_values = []
|
new_folder.custom_values = []
|
||||||
custom_values.each do |cv|
|
new_folder.custom_field_values =
|
||||||
v = CustomValue.new
|
custom_field_values.inject({}) do |h, v|
|
||||||
v.custom_field = cv.custom_field
|
h[v.custom_field_id] = v.value
|
||||||
v.value = cv.value
|
h
|
||||||
new_folder.custom_values << v
|
end
|
||||||
end
|
|
||||||
unless new_folder.save
|
unless new_folder.save
|
||||||
Rails.logger.error new_folder.errors.full_messages.to_sentence
|
Rails.logger.error new_folder.errors.full_messages.to_sentence
|
||||||
return new_folder
|
return new_folder
|
||||||
@ -601,6 +600,15 @@ class DmsfFolder < ApplicationRecord
|
|||||||
title
|
title
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Check whether any child folder is equal to the folder
|
||||||
|
def any_child?(folder)
|
||||||
|
dmsf_folders.each do |child|
|
||||||
|
return true if child == folder
|
||||||
|
child.any_child? folder
|
||||||
|
end
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def directory_subtree(tree, folder, level, current_folder)
|
def directory_subtree(tree, folder, level, current_folder)
|
||||||
folders = folder.dmsf_folders.visible.to_a
|
folders = folder.dmsf_folders.visible.to_a
|
||||||
|
|||||||
75
app/views/dmsf/copymove.html.erb
Normal file
75
app/views/dmsf/copymove.html.erb
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<%
|
||||||
|
# Redmine plugin for Document Management System "Features"
|
||||||
|
#
|
||||||
|
# Copyright © 2011 Vít Jonáš <vit.jonas@gmail.com>
|
||||||
|
# Copyright © 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||||
|
# Copyright © 2011-23 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.
|
||||||
|
%>
|
||||||
|
|
||||||
|
<%= render partial: '/dmsf/path', locals: { folder: nil, filename: nil, title: nil } %>
|
||||||
|
|
||||||
|
<% if @projects.present? || @fast_links %>
|
||||||
|
<%= form_tag(entries_operations_dmsf_path, id: 'copyForm') do %>
|
||||||
|
<% @ids.each do |id| %>
|
||||||
|
<%= hidden_field_tag 'ids[]', id %>
|
||||||
|
<% end %>
|
||||||
|
<%= hidden_field_tag 'back_url', @back_url %>
|
||||||
|
<%= hidden_field_tag 'id', @project %>
|
||||||
|
<%= hidden_field_tag 'copy_entries', true %>
|
||||||
|
<div class="box tabular">
|
||||||
|
<% unless @fast_links %>
|
||||||
|
<p>
|
||||||
|
<%= label_tag 'dmsf_entries[target_project_id]', l(:field_target_project) %>
|
||||||
|
<%= select_tag 'dmsf_entries[target_project_id]',
|
||||||
|
project_tree_options_for_select(@projects, selected: @target_project) %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<p>
|
||||||
|
<%= label_tag 'dmsf_entries[target_folder_id]', l(:field_target_folder) %><%= ' #' if @fast_links %>
|
||||||
|
<% if @fast_links %>
|
||||||
|
<%= text_field_tag 'dmsf_entries[target_folder_id]', '', required: true, max_length: 255 %>
|
||||||
|
<% else %>
|
||||||
|
<%= select_tag 'dmsf_entries[target_folder_id]', options_for_select(@folders, selected: @target_folder&.id) %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<%= submit_tag l(:button_copy), id: 'copy_button' %>
|
||||||
|
<%# TODO: Lock and proper permissions %>
|
||||||
|
<% if User.current.allowed_to?(:folder_manipulation, @project) &&
|
||||||
|
User.current.allowed_to?(:file_manipulation, @project)%>
|
||||||
|
<%= submit_tag l(:button_move), id: 'move_button' %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= late_javascript_tag do %>
|
||||||
|
$('#move_button').click(function(event) {
|
||||||
|
$('#copyForm').attr('action', "<%= entries_operations_dmsf_path(ids: @ids, move_entries: true) %>");
|
||||||
|
$('#copyForm').submit();
|
||||||
|
});
|
||||||
|
<% unless @fast_links %>
|
||||||
|
$('#dmsf_entries_target_project_id').change(function () {
|
||||||
|
$('#content').load("<%= copymove_entries_path(id: @project, folder_id: @folder, ids: @ids) %>",
|
||||||
|
$('#copyForm').serialize());
|
||||||
|
});
|
||||||
|
$('#dmsf_entries_target_project_id').select2();
|
||||||
|
$('#dmsf_entries_target_folder_id').select2();
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
@ -24,8 +24,8 @@
|
|||||||
</li>
|
</li>
|
||||||
<% unless dmsf_link %>
|
<% unless dmsf_link %>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to "#{l(:button_copy)}/#{l(:button_move)}", copy_file_path(id: dmsf_file, back_url: back_url),
|
<%= context_menu_link "#{l(:button_copy)}/#{l(:button_move)}", copymove_entries_path(id: project, folder_id: folder,
|
||||||
title: l(:title_copy), class: 'icon icon-copy' %>
|
ids: ["file-#{dmsf_file.id}"], back_url: back_url), class: 'icon icon-copy' %>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to l(:label_link_to),
|
<%= link_to l(:label_link_to),
|
||||||
|
|||||||
@ -26,8 +26,8 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<% unless dmsf_link %>
|
<% unless dmsf_link %>
|
||||||
<li>
|
<li>
|
||||||
<%= context_menu_link "#{l(:button_copy)}/#{l(:button_move)}", copy_folder_path(id: dmsf_folder, back_url: back_url),
|
<%= context_menu_link "#{l(:button_copy)}/#{l(:button_move)}", copymove_entries_path(id: project, folder_id: folder,
|
||||||
class: 'icon icon-copy', disabled: !allowed || locked %>
|
ids: ["folder-#{dmsf_folder.id}"], back_url: back_url), class: 'icon icon-copy', disabled: !allowed || locked %>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= context_menu_link l(:label_link_to),
|
<%= context_menu_link l(:label_link_to),
|
||||||
|
|||||||
@ -27,9 +27,12 @@
|
|||||||
ids: params[:ids], email_entries: true), method: :post, class: 'icon icon-email',
|
ids: params[:ids], email_entries: true), method: :post, class: 'icon icon-email',
|
||||||
disabled: !email_allowed %>
|
disabled: !email_allowed %>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<%= context_menu_link "#{l(:button_copy)}/#{l(:button_move)}", copymove_entries_path(id: project, folder_id: folder,
|
||||||
|
ids: params[:ids], back_url: back_url), class: 'icon icon-copy', disabled: project.nil? %>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= context_menu_link l(:button_delete), entries_operations_dmsf_path(id: project, folder_id: folder,
|
<%= context_menu_link l(:button_delete), entries_operations_dmsf_path(id: project, folder_id: folder,
|
||||||
ids: params[:ids], delete_entries: true), method: :post, class: 'icon icon-del',
|
ids: params[:ids], delete_entries: true), method: :post, class: 'icon icon-del',
|
||||||
data: { confirm: l(:text_are_you_sure) }, id: 'dmsf-cm-delete',
|
data: { confirm: l(:text_are_you_sure) }, id: 'dmsf-cm-delete', disabled: !allowed %>
|
||||||
disabled: !allowed %>
|
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -36,8 +36,8 @@
|
|||||||
dmsf_file_id: file.id, type: 'link_to', back_url: back_url),
|
dmsf_file_id: file.id, type: 'link_to', back_url: back_url),
|
||||||
title: l(:title_create_link),
|
title: l(:title_create_link),
|
||||||
class: 'icon dmsf-icon-link' %>
|
class: 'icon dmsf-icon-link' %>
|
||||||
<%= link_to "#{l(:button_copy)}/#{l(:button_move)}", copy_file_path(id: file, back_url: back_url),
|
<%= context_menu_link "#{l(:button_copy)}/#{l(:button_move)}", copymove_entries_path(id: project,
|
||||||
title: l(:title_copy), class: 'icon icon-copy' %>
|
folder_id: file.dmsf_folder, ids: ["file-#{file.id}"], back_url: back_url), class: 'icon icon-copy' %>
|
||||||
<% member = Member.find_by(user_id: User.current.id, project_id: file.project.id) %>
|
<% member = Member.find_by(user_id: User.current.id, project_id: file.project.id) %>
|
||||||
<% filename = file.last_revision&.formatted_name(member) %>
|
<% filename = file.last_revision&.formatted_name(member) %>
|
||||||
<%= link_to l(:button_download), static_dmsf_file_path(file, filename: filename), class: 'icon icon-download',
|
<%= link_to l(:button_download), static_dmsf_file_path(file, filename: filename), class: 'icon icon-download',
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
<%
|
|
||||||
# Redmine plugin for Document Management System "Features"
|
|
||||||
#
|
|
||||||
# Copyright © 2011 Vít Jonáš <vit.jonas@gmail.com>
|
|
||||||
# Copyright © 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
|
||||||
# Copyright © 2011-23 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.
|
|
||||||
%>
|
|
||||||
|
|
||||||
<%= render partial: '/dmsf/path', locals: { folder: @file.dmsf_folder, filename: @file.title, title: nil } %>
|
|
||||||
|
|
||||||
<%= render partial: '/dmsf_folders_copy/form',
|
|
||||||
locals: {
|
|
||||||
projects: @projects,
|
|
||||||
project: @project,
|
|
||||||
target_project: @target_project,
|
|
||||||
folders: @folders,
|
|
||||||
file_or_folder: @file,
|
|
||||||
target_folder: @target_folder,
|
|
||||||
permission: :file_manipulation,
|
|
||||||
fast_links: @fast_links,
|
|
||||||
back_url: @back_url } %>
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
<%
|
|
||||||
# Redmine plugin for Document Management System "Features"
|
|
||||||
#
|
|
||||||
# Copyright © 2011-23 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.
|
|
||||||
%>
|
|
||||||
|
|
||||||
<% if projects.present? || fast_links %>
|
|
||||||
<%= form_tag({ action: 'copy', id: file_or_folder}, id: 'copyForm') do %>
|
|
||||||
<%= hidden_field_tag 'back_url', back_url %>
|
|
||||||
<div class="box tabular">
|
|
||||||
<% unless fast_links %>
|
|
||||||
<p>
|
|
||||||
<%= label_tag 'dmsf_file_or_folder[target_project_id]', l(:field_target_project) %>
|
|
||||||
<%= select_tag 'dmsf_file_or_folder[target_project_id]',
|
|
||||||
project_tree_options_for_select(projects, selected: target_project) %>
|
|
||||||
</p>
|
|
||||||
<% end %>
|
|
||||||
<p>
|
|
||||||
<%= label_tag 'dmsf_file_or_folder[target_folder_id]', l(:field_target_folder) %><%= ' #' if fast_links %>
|
|
||||||
<% if fast_links %>
|
|
||||||
<%= text_field_tag 'dmsf_file_or_folder[target_folder_id]', '', required: true, max_length: 255 %>
|
|
||||||
<% else %>
|
|
||||||
<%= select_tag 'dmsf_file_or_folder[target_folder_id]',
|
|
||||||
options_for_select(folders, selected: (target_folder.id if target_folder)) %>
|
|
||||||
<% end %>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<%= submit_tag l(:button_copy), id: 'copy_button' %>
|
|
||||||
<% if !file_or_folder.locked? && User.current.allowed_to?(permission, project) %>
|
|
||||||
<%= submit_tag l(:button_move), id: 'move_button' %>
|
|
||||||
<% end %>
|
|
||||||
</p>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= late_javascript_tag do %>
|
|
||||||
$('#move_button').click(function(event) {
|
|
||||||
$('#copyForm').attr('action', "<%= url_for(action: 'move', id: file_or_folder) %>");
|
|
||||||
$('#copyForm').submit();
|
|
||||||
});
|
|
||||||
<% unless fast_links %>
|
|
||||||
$('#dmsf_file_or_folder_target_project_id').change(function () {
|
|
||||||
$('#content').load("<%= url_for(action: 'new') %>", $('#copyForm').serialize());
|
|
||||||
});
|
|
||||||
$('#dmsf_file_or_folder_target_project_id').select2();
|
|
||||||
$('#dmsf_file_or_folder_target_folder_id').select2();
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
<%
|
|
||||||
# Redmine plugin for Document Management System "Features"
|
|
||||||
#
|
|
||||||
# Copyright © 2011 Vít Jonáš <vit.jonas@gmail.com>
|
|
||||||
# Copyright © 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
|
||||||
# Copyright © 2011-23 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.
|
|
||||||
%>
|
|
||||||
|
|
||||||
<%= render partial: '/dmsf/path', locals: { folder: @folder, filename: nil, title: nil } %>
|
|
||||||
|
|
||||||
<%= render partial: '/dmsf_folders_copy/form', locals: {
|
|
||||||
projects: @projects,
|
|
||||||
project: @project,
|
|
||||||
target_project: @target_project,
|
|
||||||
folders: @folders,
|
|
||||||
file_or_folder: @folder,
|
|
||||||
target_folder: @target_folder,
|
|
||||||
permission: :folder_manipulation,
|
|
||||||
fast_links: @fast_links,
|
|
||||||
back_url: @back_url} %>
|
|
||||||
@ -473,6 +473,9 @@ cs:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-textové vyhledávání v dokumentech vyžaduje přítomnost %{cmd1} and %{cmd2} na serveru.'
|
text_fulltext_search: 'Full-textové vyhledávání v dokumentech vyžaduje přítomnost %{cmd1} and %{cmd2} na serveru.'
|
||||||
|
|
||||||
|
notice_entries_copied: Kopírování se podařilo
|
||||||
|
notice_entries_moved: Přesun se podařil
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -469,6 +469,9 @@ de:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text Suche in Dokumente fordert die Existenz %{cmd1} and %{cmd2} auf dem Server.'
|
text_fulltext_search: 'Full-text Suche in Dokumente fordert die Existenz %{cmd1} and %{cmd2} auf dem Server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Kopieren ist gelungen
|
||||||
|
notice_entries_moved: Verschiebung ist gelungen
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: Von mir gesperrte Dokumente
|
dmsf_locked_documents: Von mir gesperrte Dokumente
|
||||||
|
|||||||
@ -473,6 +473,9 @@ en:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -473,6 +473,9 @@ es:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -452,6 +452,9 @@ fa:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: اسناد قفل شدهی من
|
dmsf_locked_documents: اسناد قفل شدهی من
|
||||||
|
|||||||
@ -473,6 +473,9 @@ fr:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -472,6 +472,9 @@ hu:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -473,6 +473,9 @@ it: # Italian strings thx 2 Matteo Arceci!
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -474,6 +474,9 @@ ja:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: 自分がロック中の文書
|
dmsf_locked_documents: 自分がロック中の文書
|
||||||
|
|||||||
@ -473,6 +473,9 @@ ko:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: 내 잠긴 파일
|
dmsf_locked_documents: 내 잠긴 파일
|
||||||
|
|||||||
@ -473,6 +473,9 @@ nl:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -472,6 +472,9 @@ pl:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -473,6 +473,9 @@ pt-BR:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -473,6 +473,9 @@ sl:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -475,6 +475,9 @@ uk:
|
|||||||
|
|
||||||
text_fulltext_search: 'Повнотекстовий пошук вимагає наявності %{cmd1} та %{cmd2} команд на сервері.'
|
text_fulltext_search: 'Повнотекстовий пошук вимагає наявності %{cmd1} та %{cmd2} команд на сервері.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: Мої заблоковані документи
|
dmsf_locked_documents: Мої заблоковані документи
|
||||||
|
|||||||
@ -472,6 +472,9 @@ zh-TW:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -473,6 +473,9 @@ zh:
|
|||||||
|
|
||||||
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
text_fulltext_search: 'Full-text search in documents requires presence of %{cmd1} and %{cmd2} commands on the server.'
|
||||||
|
|
||||||
|
notice_entries_copied: Copying has succeeded
|
||||||
|
notice_entries_moved: Moving has succeeded
|
||||||
|
|
||||||
easy_pages:
|
easy_pages:
|
||||||
modules:
|
modules:
|
||||||
dmsf_locked_documents: My locked documents
|
dmsf_locked_documents: My locked documents
|
||||||
|
|||||||
@ -42,6 +42,7 @@ if Redmine::Plugin.installed? 'redmine_dmsf'
|
|||||||
get '/projects/:id/dmsf/entries/download_email_entries', controller: 'dmsf',
|
get '/projects/:id/dmsf/entries/download_email_entries', controller: 'dmsf',
|
||||||
action: 'download_email_entries',
|
action: 'download_email_entries',
|
||||||
as: 'download_email_entries'
|
as: 'download_email_entries'
|
||||||
|
get '/projects/:id/entries/copymove', to: 'dmsf#copymove', as: 'copymove_entries'
|
||||||
get '/projects/:id/dmsf/lock', controller: 'dmsf', action: 'lock', as: 'lock_dmsf'
|
get '/projects/:id/dmsf/lock', controller: 'dmsf', action: 'lock', as: 'lock_dmsf'
|
||||||
get '/projects/:id/dmsf/unlock', controller: 'dmsf', action: 'unlock', as: 'unlock_dmsf'
|
get '/projects/:id/dmsf/unlock', controller: 'dmsf', action: 'unlock', as: 'unlock_dmsf'
|
||||||
get '/projects/:id/dmsf/', controller: 'dmsf', action: 'show', as: 'dmsf_folder'
|
get '/projects/:id/dmsf/', controller: 'dmsf', action: 'show', as: 'dmsf_folder'
|
||||||
|
|||||||
29
lib/redmine_dmsf/errors/dmsf_parent_error.rb
Normal file
29
lib/redmine_dmsf/errors/dmsf_parent_error.rb
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Redmine plugin for Document Management System "Features"
|
||||||
|
#
|
||||||
|
# Copyright © 2011 Vít Jonáš <vit.jonas@gmail.com>
|
||||||
|
# Copyright © 2011-23 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.
|
||||||
|
|
||||||
|
module RedmineDmsf
|
||||||
|
module Errors
|
||||||
|
# Parent error
|
||||||
|
class DmsfParentError < StandardError
|
||||||
|
# Nothing to do
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -454,4 +454,138 @@ class DmsfControllerTest < RedmineDmsf::Test::TestCase
|
|||||||
get :index
|
get :index
|
||||||
assert_response :forbidden
|
assert_response :forbidden
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_copymove_authorize_admin
|
||||||
|
@request.session[:user_id] = @admin.id
|
||||||
|
get :copymove, params: { id: @file1.project, folder_id: @file1.dmsf_folder, ids: ["file-#{@file1.id}"] }
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'copymove'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_copymove_authorize_non_member
|
||||||
|
@request.session[:user_id] = @someone.id
|
||||||
|
get :copymove, params: { id: @file1.project, folder_id: @file1.dmsf_folder, ids: ["file-#{@file1.id}"] }
|
||||||
|
assert_response :forbidden
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_copymove_authorize_member_no_module
|
||||||
|
@file1.project.disable_module! :dmsf
|
||||||
|
get :copymove, params: { id: @file1.project, folder_id: @file1.dmsf_folder, ids: ["file-#{@file1.id}"] }
|
||||||
|
assert_response :forbidden
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_copymove_authorize_forbidden
|
||||||
|
@role_manager.remove_permission! :folder_manipulation
|
||||||
|
get :copymove, params: { id: @file1.project, folder_id: @file1.dmsf_folder, ids: ["file-#{@file1.id}"] }
|
||||||
|
assert_response :forbidden
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_copymove_target_folder
|
||||||
|
get :copymove, params: { id: @file1.project, folder_id: @file1.dmsf_folder, ids: ["file-#{@file1.id}"] }
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'copymove'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_copy
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @file1.project,
|
||||||
|
dmsf_entries: { target_project_id: @folder1.project.id, target_folder_id: @folder1.id },
|
||||||
|
ids: ["file-#{@file1.id}"],
|
||||||
|
copy_entries: true }
|
||||||
|
assert_response :redirect
|
||||||
|
assert_nil flash[:error]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_copy
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @file1.project,
|
||||||
|
dmsf_entries: { target_project_id: @file1.project.id, target_folder_id: @file1.dmsf_folder },
|
||||||
|
ids: ["file-#{@file1.id}"],
|
||||||
|
copy_entries: true }
|
||||||
|
assert_response :redirect
|
||||||
|
assert_equal flash[:error], l(:error_target_folder_same)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_move_recursion
|
||||||
|
# Move a folder under the same folder
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @folder1.project,
|
||||||
|
dmsf_entries: { target_project_id: @folder2.project.id, target_folder_id: @folder2.id },
|
||||||
|
ids: ["folder-#{@folder1.id}"],
|
||||||
|
move_entries: true }
|
||||||
|
assert_response :redirect
|
||||||
|
assert_equal flash[:error], l(:error_target_folder_same)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_move_infinity
|
||||||
|
# Move the folder to itself
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @folder1.project,
|
||||||
|
dmsf_entries: { target_project_id: @folder2.project.id, target_folder_id: @folder2.id },
|
||||||
|
ids: ["folder-#{@folder2.id}"],
|
||||||
|
move_entries: true }
|
||||||
|
assert_response :redirect
|
||||||
|
assert_equal flash[:error], l(:error_target_folder_same)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_copy_to_locked_folder
|
||||||
|
@request.session[:user_id] = @admin.id
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @folder1.project,
|
||||||
|
dmsf_entries: { target_project_id: @folder2.project.id, target_folder_id: @folder2.id },
|
||||||
|
ids: ["file-#{@file1.id}"],
|
||||||
|
move_entries: true }
|
||||||
|
assert_response :forbidden
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_copy_to_dmsf_not_enabled
|
||||||
|
@project2.disable_module! :dmsf
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @project2.id,
|
||||||
|
dmsf_entries: { target_project_id: @project2.id },
|
||||||
|
ids: ["file-#{@file1.id}"],
|
||||||
|
copy_entries: true }
|
||||||
|
assert_response :forbidden
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_copy_to_dmsf_enabled
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @project2.id,
|
||||||
|
dmsf_entries: { target_project_id: @project2.id },
|
||||||
|
ids: ["file-#{@file1.id}"],
|
||||||
|
copy_entries: true }
|
||||||
|
assert_response :redirect
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_copy_to_as_non_member
|
||||||
|
@request.session[:user_id] = @someone.id
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @project2.id,
|
||||||
|
dmsf_entries: { target_project_id: @project2.id },
|
||||||
|
ids: ["file-#{@file1.id}"],
|
||||||
|
copy_entries: true }
|
||||||
|
assert_response :forbidden
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_copymove_new_fast_links_enabled
|
||||||
|
member = Member.find_by(user_id: @jsmith.id, project_id: @project1.id)
|
||||||
|
assert member
|
||||||
|
member.dmsf_fast_links = true
|
||||||
|
member.save
|
||||||
|
get :copymove, params: { id: @file1.project, folder_id: @file1.dmsf_folder, ids: ["file-#{@file4.id}"] }
|
||||||
|
assert_response :success
|
||||||
|
assert_select 'label', { count: 0, text: l(:label_target_project) }
|
||||||
|
assert_select 'label', { count: 0, text: "#{l(:label_target_folder)}#" }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entries_move_fast_links_enabled
|
||||||
|
# Target project is not given
|
||||||
|
post :entries_operation,
|
||||||
|
params: { id: @project1.id,
|
||||||
|
dmsf_entries: { target_folder_id: @folder1.id },
|
||||||
|
ids: ["file-#{@file1.id}"],
|
||||||
|
move_entries: true }
|
||||||
|
assert_response :redirect
|
||||||
|
assert_nil flash[:error]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,142 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# Redmine plugin for Document Management System "Features"
|
|
||||||
#
|
|
||||||
# Copyright © 2011-23 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.
|
|
||||||
|
|
||||||
require File.expand_path('../../test_helper', __FILE__)
|
|
||||||
|
|
||||||
# Files controller
|
|
||||||
class DmsfFilesControllerTest < RedmineDmsf::Test::TestCase
|
|
||||||
fixtures :dmsf_folders, :dmsf_files, :dmsf_file_revisions, :dmsf_locks
|
|
||||||
|
|
||||||
def setup
|
|
||||||
super
|
|
||||||
@request.session[:user_id] = @jsmith.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def teardown
|
|
||||||
super
|
|
||||||
DmsfFile.clear_previews
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_show_file_ok
|
|
||||||
# Permissions OK
|
|
||||||
get :show, params: { id: @file1.id }
|
|
||||||
assert_response :success
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_show_formatting_html
|
|
||||||
Setting.text_formatting = 'HTML'
|
|
||||||
get :show, params: { id: @file1.id }
|
|
||||||
assert_response :success
|
|
||||||
assert_include 'dmsf-description', response.body, 'dmsf-description class not found'
|
|
||||||
assert_include 'wiki-edit', response.body, 'wiki-edit class not found'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_show_formatting_textile
|
|
||||||
Setting.text_formatting = 'Textile'
|
|
||||||
get :show, params: { id: @file1.id }
|
|
||||||
assert_response :success
|
|
||||||
assert_include 'dmsf-description', response.body, 'dmsf-description class not found'
|
|
||||||
assert_include 'wiki-edit', response.body, 'wiki-edit class not found'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_show_file_forbidden
|
|
||||||
# Missing permissions
|
|
||||||
@role_manager.remove_permission! :view_dmsf_files
|
|
||||||
get :show, params: { id: @file1.id }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_view_file_ok
|
|
||||||
# Permissions OK
|
|
||||||
get :view, params: { id: @file1.id }
|
|
||||||
assert_response :success
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_view_file_forbidden
|
|
||||||
# Missing permissions
|
|
||||||
@role_manager.remove_permission! :view_dmsf_files
|
|
||||||
get :view, params: { id: @file1.id }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_view_preview
|
|
||||||
return unless RedmineDmsf::Preview.office_available?
|
|
||||||
|
|
||||||
get :view, params: { id: @file13.id }
|
|
||||||
assert_response :success
|
|
||||||
assert_equal 'application/pdf', @response.media_type
|
|
||||||
assert @response.body.starts_with?('%PDF')
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete_forbidden
|
|
||||||
# Missing permissions
|
|
||||||
@role_manager.remove_permission! :file_manipulation
|
|
||||||
delete :delete, params: { id: @file1, folder_id: @file1.dmsf_folder, commit: false }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete_locked
|
|
||||||
# Permissions OK but the file is locked
|
|
||||||
delete :delete, params: { id: @file2, folder_id: @file2.dmsf_folder, commit: false }
|
|
||||||
assert_response :redirect
|
|
||||||
assert_include l(:error_file_is_locked), flash[:error]
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete_ok
|
|
||||||
# Permissions OK and not locked
|
|
||||||
delete :delete, params: { id: @file1, folder_id: @file1.dmsf_folder, commit: false }
|
|
||||||
assert_redirected_to dmsf_folder_path(id: @file1.project, folder_id: @file1.dmsf_folder)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_delete_in_subfolder
|
|
||||||
delete :delete, params: { id: @file4, folder_id: @file4.dmsf_folder, commit: false }
|
|
||||||
assert_redirected_to dmsf_folder_path(id: @file4.project, folder_id: @file4.dmsf_folder)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_obsolete_revision_ok
|
|
||||||
get :obsolete_revision, params: { id: @file1.last_revision.id }
|
|
||||||
assert_redirected_to action: 'show', id: @file1
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_obsolete_revision_missing_permissions
|
|
||||||
@role_manager.remove_permission! :file_manipulation
|
|
||||||
get :obsolete_revision, params: { id: @file1.last_revision.id }
|
|
||||||
assert :forbiden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_create_revision
|
|
||||||
assert_difference 'DmsfFileRevision.count', +1 do
|
|
||||||
post :create_revision,
|
|
||||||
params: {
|
|
||||||
id: @file1.id,
|
|
||||||
version_major: @file1.last_revision.major_version,
|
|
||||||
version_minor: @file1.last_revision.minor_version + 1,
|
|
||||||
dmsf_file_revision: {
|
|
||||||
title: @file1.last_revision.title,
|
|
||||||
name: @file1.last_revision.name,
|
|
||||||
description: @file1.last_revision.description,
|
|
||||||
comment: 'New revision'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
assert_redirected_to dmsf_folder_path(id: @file1.project)
|
|
||||||
assert_not_nil @file1.last_revision.digest
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,199 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# Redmine plugin for Document Management System "Features"
|
|
||||||
#
|
|
||||||
# Copyright © 2011-23 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.
|
|
||||||
|
|
||||||
require File.expand_path('../../test_helper', __FILE__)
|
|
||||||
|
|
||||||
# Folders copy controller
|
|
||||||
class DmsfFoldersCopyControllerTest < RedmineDmsf::Test::TestCase
|
|
||||||
include Redmine::I18n
|
|
||||||
|
|
||||||
fixtures :dmsf_locks, :dmsf_folders, :dmsf_files, :dmsf_file_revisions
|
|
||||||
|
|
||||||
def setup
|
|
||||||
super
|
|
||||||
@request.session[:user_id] = @jsmith.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_authorize_admin
|
|
||||||
@request.session[:user_id] = @admin.id
|
|
||||||
get :new, params: { id: @folder1.id }
|
|
||||||
assert_response :success
|
|
||||||
assert_template 'new'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_authorize_non_member
|
|
||||||
@request.session[:user_id] = @someone.id
|
|
||||||
get :new, params: { id: @folder1.id }
|
|
||||||
assert_response :not_found
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_authorize_member_no_module
|
|
||||||
@project1.disable_module! :dmsf
|
|
||||||
get :new, params: { id: @folder1.id }
|
|
||||||
assert_response :not_found
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_authorize_forbidden
|
|
||||||
@role_manager.remove_permission! :folder_manipulation
|
|
||||||
get :new, params: { id: @folder1.id }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_target_folder
|
|
||||||
get :new, params: { id: @folder1.id, target_folder_id: @folder2.id }
|
|
||||||
assert_response :success
|
|
||||||
assert_template 'new'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_target_folder_forbidden
|
|
||||||
@role_manager.remove_permission! :view_dmsf_folders
|
|
||||||
get :new, params: { id: @folder1.id, target_folder_id: @folder2.id }
|
|
||||||
assert_response :not_found
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_target_project
|
|
||||||
get :new, params: { id: @folder1.id, target_project_id: @project1.id }
|
|
||||||
assert_response :success
|
|
||||||
assert_template 'new'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_new
|
|
||||||
get :new, params: { id: @folder1.id }
|
|
||||||
assert_response :success
|
|
||||||
assert_template 'new'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_copy
|
|
||||||
post :copy, params: { id: @folder1.id, dmsf_file_or_folder: { target_project_id: @project1.id,
|
|
||||||
target_folder_id: @folder6.id } }
|
|
||||||
assert_response :redirect
|
|
||||||
assert_nil flash[:error]
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_copy_to_another_project
|
|
||||||
@request.session[:user_id] = @admin.id
|
|
||||||
assert_equal @project1.id, @folder1.project_id
|
|
||||||
post :copy, params: { id: @folder1.id, dmsf_file_or_folder: { target_project_id: @project2.id } }
|
|
||||||
assert_response :redirect
|
|
||||||
assert_nil flash[:error]
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_copy_the_same_target
|
|
||||||
post :copy, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @folder6.project.id } }
|
|
||||||
assert_equal flash[:error], l(:error_target_folder_same)
|
|
||||||
assert_redirected_to action: :new, target_project_id: @folder6.project.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_copy_to_locked_folder
|
|
||||||
@request.session[:user_id] = @admin.id
|
|
||||||
post :copy, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @folder2.project.id,
|
|
||||||
target_folder_id: @folder2.id } }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_copy_to_dmsf_not_enabled
|
|
||||||
@project2.disable_module! :dmsf
|
|
||||||
post :copy, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @project2.id } }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_copy_to_dmsf_enabled
|
|
||||||
post :copy, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @project2.id } }
|
|
||||||
assert_response :redirect
|
|
||||||
assert_nil flash[:error]
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_copy_to_as_non_member
|
|
||||||
@request.session[:user_id] = @someone.id
|
|
||||||
post :copy, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @folder1.project.id,
|
|
||||||
target_folder_id: @folder1.id } }
|
|
||||||
assert_response :not_found
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move
|
|
||||||
post :move, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @folder1.project.id,
|
|
||||||
target_folder_id: @folder1.id } }
|
|
||||||
assert_response :redirect
|
|
||||||
assert_nil flash[:error]
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move_to_another_project
|
|
||||||
post :move, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @project2.id } }
|
|
||||||
assert_response :redirect
|
|
||||||
assert_nil flash[:error]
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move_the_same_target
|
|
||||||
post :move, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @folder6.project.id } }
|
|
||||||
assert_equal flash[:error], l(:error_target_folder_same)
|
|
||||||
assert_redirected_to action: :new, target_project_id: @folder6.project.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move_locked_folder
|
|
||||||
@request.session[:user_id] = @admin.id
|
|
||||||
post :move, params: { id: @folder2.id, dmsf_file_or_folder: { target_project_id: @folder6.project.id,
|
|
||||||
target_folder_id: @folder6.id } }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move_to_locked_folder
|
|
||||||
@request.session[:user_id] = @admin.id
|
|
||||||
post :move, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @folder2.project.id,
|
|
||||||
target_folder_id: @folder2.id } }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move_to_dmsf_not_enabled
|
|
||||||
@project2.disable_module! :dmsf
|
|
||||||
post :move, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @project2.id } }
|
|
||||||
assert_response :forbidden
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move_to_dmsf_enabled
|
|
||||||
post :move, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @project2.id } }
|
|
||||||
assert_response :redirect
|
|
||||||
assert_nil flash[:error]
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move_to_as_non_member
|
|
||||||
@request.session[:user_id] = @someone.id
|
|
||||||
post :move, params: { id: @folder6.id, dmsf_file_or_folder: { target_project_id: @folder1.project.id,
|
|
||||||
target_folder_id: @folder1.id } }
|
|
||||||
assert_response :not_found
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_new_fast_links_enabled
|
|
||||||
member = Member.find_by(user_id: @jsmith.id, project_id: @project1.id)
|
|
||||||
assert member
|
|
||||||
member.dmsf_fast_links = true
|
|
||||||
member.save
|
|
||||||
get :new, params: { id: @folder1.id }
|
|
||||||
assert_response :success
|
|
||||||
assert_select 'label', { count: 0, text: l(:label_target_project) }
|
|
||||||
assert_select 'label', { count: 0, text: "#{l(:label_target_folder)}#" }
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_move_fast_links_enabled
|
|
||||||
# Target project is not given
|
|
||||||
post :move, params: { id: @folder6.id, dmsf_file_or_folder: { target_folder_id: @folder1.id } }
|
|
||||||
assert_response :redirect
|
|
||||||
assert_nil flash[:error]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -292,4 +292,12 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
|
|||||||
assert @folder8.save
|
assert @folder8.save
|
||||||
assert_not DmsfFolder.where(id: @folder8.id).issystem.exists?
|
assert_not DmsfFolder.where(id: @folder8.id).issystem.exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_any_child
|
||||||
|
# folder1
|
||||||
|
## folder 2
|
||||||
|
# folder6
|
||||||
|
assert_not @folder1.any_child?(@folder6)
|
||||||
|
assert @folder1.any_child?(@folder2)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user