Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use file name numbering on kit upload instead of overwriting files with the same name #1213

Open
wants to merge 13 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[v#.#.#] ([month] [YYYY])
- Attachments: Copy attachments when moving an evidence/note
- Liquid: Make project-level collections available for Liquid syntax
- Kit Import: Use file name sequencing when a template file with the same name exists
- Upgraded gems: nokogiri, rails, rexml
- Bugs fixes:
- Navigation: Restore functionality of native browser back/forward buttons
Expand Down
51 changes: 33 additions & 18 deletions app/jobs/kit_import_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class KitImportJob < ApplicationJob
'html_export' => ['html.erb'],
'word' => ['docm', 'docx']
}
TEMPLATE_TYPES = %w{ methodologies notes projects reports }

queue_as :dradis_upload

Expand All @@ -16,22 +17,27 @@ def perform(file_or_folder, logger:, user_id: nil)
@current_user = user_id ? User.find(user_id) : User.first
@logger = logger
@project = nil
@report_templates_dir = Configuration.paths_templates_reports
@templates_dirs = TEMPLATE_TYPES.map do |template_type|
[
template_type,
Pathname.new(Configuration.send("paths_templates_#{template_type}"))
]
Comment on lines +21 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to 🤓 out, you can do this in a single SQL query, by prebuilding the names from the TEMPLATE_TYPEs.

end.to_h
@working_dir = Dir.mktmpdir
@word_rtp = nil

copy_kit_to_working_dir(file_or_folder)

import_methodology_templates
import_note_templates
import_plugin_templates
import_project_package
import_project_templates
import_report_template_files

if defined?(Dradis::Pro)
import_report_template_properties
import_rules
import_mappings

assign_project_rtp
end
Expand All @@ -42,7 +48,7 @@ def perform(file_or_folder, logger:, user_id: nil)
end

private
attr_reader :current_user, :logger, :report_templates_dir, :working_dir
attr_reader :current_user, :logger, :templates_dirs, :working_dir

def assign_project_rtp
logger.info { 'Assigning RTP to project...' }
Expand All @@ -62,6 +68,12 @@ def copy_kit_to_working_dir(source)
end
end

def import_mappings
logger.info { 'Adding Mappings...' }
mappings_seed = "#{working_dir}/kit/mappings_seed.rb"
load mappings_seed if File.exist?(mappings_seed)
end

def import_methodology_templates
logger.info { 'Copying methodology templates...' }
import_templates('methodologies')
Expand Down Expand Up @@ -106,13 +118,6 @@ def import_project_package
logger.info { " - New Project #{@project.id} created." }
end

def import_plugin_templates
return unless File.directory?("#{working_dir}/kit/templates/plugins/")

logger.info { 'Copying Plugin Manager templates...' }
import_templates('plugins')
end

def import_project_templates
logger.info { 'Copying project templates...' }
import_templates('projects')
Expand All @@ -121,13 +126,13 @@ def import_project_templates
def import_report_template_files
logger.info { 'Copying report template files...' }

FileUtils.mkdir_p report_templates_dir
FileUtils.mkdir_p templates_dirs['reports']
%w{
excel
html_export
word
}.each do |plugin|
dest = "#{report_templates_dir}/#{plugin}/"
dest = "#{templates_dirs['reports']}/#{plugin}/"
temp_plugin_path = "#{working_dir}/kit/templates/reports/#{plugin}/*"

# Only allow certain file extensions
Expand All @@ -144,7 +149,7 @@ def import_report_template_properties
logger.info { 'Adding properties to report template files...' }

Dradis::Plugins.with_feature(:rtp).each do |plugin|
Dir.glob(File.join(report_templates_dir, plugin.plugin_name.to_s, '*')) do |template|
Dir.glob(File.join(templates_dirs['reports'], plugin.plugin_name.to_s, '*')) do |template|
basename = File.basename(template, '.*')
reports_dir = "#{working_dir}/kit/templates/reports"
default_properties = "#{reports_dir}/#{plugin.plugin_name}/#{basename}.rb"
Expand Down Expand Up @@ -175,12 +180,22 @@ def import_rules
end

def import_templates(template_type)
template_directory = "#{working_dir}/kit/templates/#{template_type}"
return unless Dir.exist?(template_directory)
kit_template_dir = "#{working_dir}/kit/templates/#{template_type}"
destination = templates_dirs[template_type]
return unless Dir.exist?(kit_template_dir)

Dir["#{kit_template_dir}/*"].each do |file|
return unless File.file?(file)

file_name = name_file(File.basename(file), destination)
FileUtils.cp(file, "#{destination}/#{file_name}")
end
end

FileUtils.cp_r(
"#{template_directory}/.",
Configuration.send("paths_templates_#{template_type}")
def name_file(original_filename, pathname)
NamingService.name_file(
original_filename: original_filename,
pathname: pathname
)
end

Expand Down
Binary file modified spec/fixtures/files/templates/kit.zip
Binary file not shown.
65 changes: 32 additions & 33 deletions spec/jobs/kit_import_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,16 @@
require 'rails_helper'

RSpec.describe KitImportJob do
before do
@user = create(:user)

file = File.new(Rails.root.join('spec', 'fixtures', 'files', 'templates', 'kit.zip'))
@tmp_dir = Rails.root.join('tmp', 'rspec')
FileUtils.mkdir_p @tmp_dir

# Use a temporary file for the job instead of the original fixture
FileUtils.cp file.path, @tmp_dir
@tmp_file = File.new(@tmp_dir.join('kit.zip'))

['methodologies', 'notes', 'plugins', 'projects', 'reports'].each do |item|
conf = Configuration.find_or_initialize_by(name: "admin:paths:templates:#{item}")
folder = @tmp_dir.join(item)
conf.value = folder
conf.save!
FileUtils.mkdir_p folder
end
include KitUploadMacros

allow(NoteTemplate).to receive(:pwd).and_return(
Pathname.new(Configuration.paths_templates_notes)
)
allow(Methodology).to receive(:pwd).and_return(
Pathname.new(Configuration.paths_templates_methodologies)
)
allow(ProjectTemplate).to receive(:pwd).and_return(
Pathname.new(Configuration.paths_templates_projects)
)
before do
@user = create(:user)
setup_kit_import
end

describe '#perform' do
after(:all) do
FileUtils.rm_rf(Dir.glob(Attachment.pwd + '*'))
FileUtils.rm_rf(Rails.root.join('tmp', 'rspec'))
Configuration.delete_by('name LIKE ?', 'admin:paths:%')
cleanup_kit_import
end

it 'imports kit content' do
Expand All @@ -55,9 +30,6 @@
# project template
expect(ProjectTemplate.find_template('dradis-template-welcome')).to_not be_nil

# plugin templates
expect(Dir[Configuration.paths_templates_plugins + '/nessus/*']).to_not be_empty

# report template files
expect(File.exists?(Rails.root.join('tmp', 'rspec', 'reports', 'word', 'dradis_welcome_template.v0.5.docm'))).to eq true
expect(File.exists?(Rails.root.join('tmp', 'rspec', 'reports', 'excel', 'dradis_template-excel-simple.v1.3.xlsx'))).to eq true
Expand All @@ -76,6 +48,33 @@
expect(ProjectTemplate.find_template('dradis-template-no-methodologies')).to_not be_nil
end

it 'renames project templates if template with same name already exists' do
project_template = ProjectTemplate.new(filename: 'dradis-template-welcome')
project_template.save

described_class.new.perform(@tmp_file, logger: Log.new.write('Testing...'))

expect(ProjectTemplate.find_template('dradis-template-welcome_copy-01')).to_not be_nil
end

it 'renames note templates if template with same name already exists' do
note_template = NoteTemplate.new(filename: 'evidence')
note_template.save

described_class.new.perform(@tmp_file, logger: Log.new.write('Testing...'))

expect(NoteTemplate.find('evidence_copy-01')).to_not be_nil
end

it 'renames methodology templates if template with same name already exists' do
methodology = Methodology.new(filename: 'OWASPv4_Testing_Methodology', content: '<xml/>')
methodology.save

described_class.new.perform(@tmp_file, logger: Log.new.write('Testing...'))

expect(Methodology.find('OWASPv4_Testing_Methodology_copy-01')).to_not be_nil
end

if defined?(Dradis::Pro)
it 'imports Pro-only content too' do
described_class.new.perform(@tmp_file, logger: Log.new.write('Testing...'))
Expand Down
37 changes: 37 additions & 0 deletions spec/support/kit_upload_macros.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module KitUploadMacros
extend ActiveSupport::Concern

def setup_kit_import
file = File.new(Rails.root.join('spec', 'fixtures', 'files', 'templates', 'kit.zip'))
@tmp_dir = Rails.root.join('tmp', 'rspec')
FileUtils.mkdir_p @tmp_dir

# Use a temporary file for the job instead of the original fixture
FileUtils.cp file.path, @tmp_dir
@tmp_file = File.new(@tmp_dir.join('kit.zip'))

['methodologies', 'notes', 'projects', 'reports'].each do |item|
conf = Configuration.find_or_initialize_by(name: "admin:paths:templates:#{item}")
folder = @tmp_dir.join(item)
conf.value = folder
conf.save!
FileUtils.mkdir_p folder
end

allow(NoteTemplate).to receive(:pwd).and_return(
Pathname.new(Configuration.paths_templates_notes)
)
allow(Methodology).to receive(:pwd).and_return(
Pathname.new(Configuration.paths_templates_methodologies)
)
allow(ProjectTemplate).to receive(:pwd).and_return(
Pathname.new(Configuration.paths_templates_projects)
)
end

def cleanup_kit_import
FileUtils.rm_rf(Dir.glob(Attachment.pwd + '*'))
FileUtils.rm_rf(Rails.root.join('tmp', 'rspec'))
Configuration.delete_by('name LIKE ?', 'admin:paths:%')
end
end
Loading