dradis-plugins 4.7.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a55255c245e1ce6009d032fab79a582b05e760af0942ae7893ee7bb42af99dc
4
- data.tar.gz: 350e48e4f5c7021339e0d542d7d9776bafaf44f78e23b3feae5e7f8e8d8e6d4f
3
+ metadata.gz: 76e20a999e5f8a6309b837043fc488dc8d7f8f6bafae273482f9f1027078aa04
4
+ data.tar.gz: aa7c0068193b07f847ea8f0ddb6b7a8f2fb4705922ebb3da01df2859837fe4f7
5
5
  SHA512:
6
- metadata.gz: 91ee0fb58cc17d416a403dd60b9eeae6c106f16fdc4badeda6816f171f5154da7443b0c0b9d96964bf06d32a1f7b41f94db5e7d5c15f7bf3cb4c6ee0a773b643
7
- data.tar.gz: 04af89b9742efb8803f8e8d9c934aea5fa9b38c0fa7dcf16fe0f1d23a270167ef1f2c2e46af93d9e00c47c20618467e07b862b03fb4765e799d45dbcbec8ed8b
6
+ metadata.gz: efcd0183333ddf9271c3ecca1a7c4793bb864c7e6172d46bc1f335e543ecbbfcedc640953230d976c5ba9e052df2988a5077921f78a61f95e6fa188782f44357
7
+ data.tar.gz: 0c73436e1dd6d733a37fe4ccf10519f0d710137eab88eb6170fc44756d993c142372751e7f41dbc3ca5798ae6c2494d6d1829e9ba5d68cd4b1ed341fa7c92467
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ v4.9.0 (June 2023)
2
+ - Fix deduplication of findings
3
+ - Store engine settings encrypted
4
+
5
+ v4.8.0 (April 2023)
6
+ - Add support for issue and content block states
7
+
1
8
  v4.7.0 (February 2023)
2
9
  - No changes
3
10
 
@@ -2,15 +2,18 @@ module Dradis
2
2
  module Plugins
3
3
  module Export
4
4
  class BaseController < Rails.application.config.dradis.base_export_controller_class_name.to_s.constantize
5
+ before_action :validate_scope
5
6
 
6
7
  protected
7
8
 
8
- # Protected: allows export plugins to access the options sent from the
9
- # framework via the session object (see Export#create).
10
- #
11
- # Returns a Hash with indifferent access.
12
- def export_options
13
- @export_options ||= session[:export_manager].with_indifferent_access
9
+ def export_params
10
+ params.permit(:project_id, :scope, :template)
11
+ end
12
+
13
+ def validate_scope
14
+ unless Dradis::Plugins::ContentService::Base::VALID_SCOPES.include?(params[:scope])
15
+ raise 'Something fishy is going on...'
16
+ end
14
17
  end
15
18
  end
16
19
  end
@@ -20,12 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
21
21
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
22
 
23
- spec.add_development_dependency 'bundler', '~> 1.6'
24
- spec.add_development_dependency 'rake', '~> 10.0'
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake'
25
25
  spec.add_development_dependency 'rspec-rails'
26
-
27
- # By not including Rails as a dependency, we can use the gem with different
28
- # versions of Rails (a sure recipe for disaster, I'm sure), which is needed
29
- # until we bump Dradis Pro to 4.1.
30
- # s.add_dependency 'rails', '~> 4.1.1'
31
26
  end
@@ -3,14 +3,19 @@ module Dradis::Plugins
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  module ClassMethods
6
- delegate :settings, to: :instance
6
+ delegate :encrypted_settings, :settings, to: :instance
7
7
 
8
8
  def settings_namespace
9
- @settings_namespace || plugin_name
9
+ @settings_namespace ||= plugin_name
10
+ end
11
+
12
+ def addon_encrypted_settings(namespace = nil, &block)
13
+ @settings_namespace = namespace
14
+ yield self if block_given?
10
15
  end
11
16
 
12
17
  def addon_settings(namespace = nil, &block)
13
- @settings_namespace = namespace if namespace
18
+ @settings_namespace = namespace
14
19
  yield self if block_given?
15
20
  end
16
21
 
@@ -19,8 +24,12 @@ module Dradis::Plugins
19
24
  end
20
25
  end
21
26
 
27
+ def encrypted_settings
28
+ @encrypted_settings ||= Dradis::Plugins::Settings.new(self.class.settings_namespace, adapter: :encrypted_configuration)
29
+ end
30
+
22
31
  def settings
23
- @settings ||= Dradis::Plugins::Settings.new(self.class.settings_namespace)
32
+ @settings ||= Dradis::Plugins::Settings.new(self.class.settings_namespace, adapter: :db)
24
33
  end
25
34
  end
26
35
  end
@@ -10,6 +10,8 @@ require 'dradis/plugins/content_service/properties'
10
10
 
11
11
  module Dradis::Plugins::ContentService
12
12
  class Base
13
+ VALID_SCOPES = %w[all published].freeze
14
+
13
15
  include Core
14
16
 
15
17
  include Boards
@@ -3,23 +3,34 @@ module Dradis::Plugins::ContentService
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  def all_content_blocks
6
- project.content_blocks
6
+ case scope
7
+ when :all
8
+ project.content_blocks
9
+ when :published
10
+ project.content_blocks.published
11
+ else
12
+ raise 'Unsupported scope!'
13
+ end
7
14
  end
8
15
 
9
16
  def create_content_block(args={})
10
17
  block_group = args.fetch(:block_group, default_content_block_group)
11
18
  content = args.fetch(:content, default_content_block_content)
19
+ state = args.fetch(:state, :published)
12
20
  user_id = args.fetch(:user_id)
13
21
 
14
22
  content_block = ContentBlock.new(
15
23
  content: content,
16
24
  block_group: block_group,
17
25
  project_id: project.id,
26
+ state: state,
18
27
  user_id: user_id
19
28
  )
20
29
 
21
30
  if content_block.valid?
22
31
  content_block.save
32
+
33
+ return content_block
23
34
  else
24
35
  try_rescue_from_length_validation(
25
36
  model: content_block,
@@ -3,7 +3,7 @@ module Dradis::Plugins::ContentService
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- attr_accessor :logger, :plugin, :project
6
+ attr_accessor :logger, :plugin, :project, :scope
7
7
  end
8
8
 
9
9
  # ----------------------------------------------------------- Initializer
@@ -12,9 +12,11 @@ module Dradis::Plugins::ContentService
12
12
  # @option plugin [Class] the 'wrapper' module of a plugin, e.g.
13
13
  # Dradis::Plugins::Nessus
14
14
  def initialize(args={})
15
- @logger = args.fetch(:logger, Rails.logger)
16
- @plugin = args.fetch(:plugin)
15
+ @logger = args.fetch(:logger, Rails.logger)
16
+ @plugin = args.fetch(:plugin)
17
17
  @project = args[:project]
18
+ @scope = args.fetch(:scope, :published)
19
+ @state = args[:state]
18
20
  end
19
21
 
20
22
  private
@@ -3,7 +3,17 @@ module Dradis::Plugins::ContentService
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  def all_issues
6
- project.issues.where(category_id: default_issue_category.id)
6
+ issues =
7
+ case scope
8
+ when :all
9
+ project.issues
10
+ when :published
11
+ project.issues.published
12
+ else
13
+ raise 'Unsupported scope!'
14
+ end
15
+
16
+ issues.where(category_id: default_issue_category.id)
7
17
  end
8
18
 
9
19
  def create_issue(args={})
@@ -11,6 +21,7 @@ module Dradis::Plugins::ContentService
11
21
  # NOTE that ID is the unique issue identifier assigned by the plugin,
12
22
  # and is not to be confused with the Issue#id primary key
13
23
  id = args.fetch(:id, default_issue_id)
24
+ state = args.fetch(:state, @state)
14
25
 
15
26
  # Bail if we already have this issue in the cache
16
27
  uuid = [plugin::Engine::plugin_name, id]
@@ -25,9 +36,10 @@ module Dradis::Plugins::ContentService
25
36
  text << plugin_details
26
37
 
27
38
  issue = Issue.new(text: text) do |i|
28
- i.author = default_author
29
- i.node = project.issue_library
39
+ i.author = default_author
40
+ i.node = project.issue_library
30
41
  i.category = default_issue_category
42
+ i.state = state
31
43
  end
32
44
 
33
45
  if issue.valid?
@@ -64,7 +76,7 @@ module Dradis::Plugins::ContentService
64
76
  # the issue library cache has been initialized.
65
77
  def issue_cache
66
78
  @issue_cache ||= begin
67
- issues_map = all_issues.map do |issue|
79
+ issues_map = project.issues.map do |issue|
68
80
  cache_key = [
69
81
  issue.fields['plugin'],
70
82
  issue.fields['plugin_id']
@@ -5,7 +5,7 @@ module Dradis
5
5
  module Plugins
6
6
  module Export
7
7
  class Base
8
- attr_accessor :content_service, :logger, :options, :plugin, :project
8
+ attr_accessor :content_service, :logger, :options, :plugin, :project, :scope
9
9
 
10
10
  def initialize(args={})
11
11
  # Save everything just in case the implementing class needs any of it.
@@ -15,6 +15,7 @@ module Dradis
15
15
  @logger = args.fetch(:logger, Rails.logger)
16
16
  @plugin = args[:plugin] || default_plugin
17
17
  @project = args.key?(:project_id) ? Project.find(args[:project_id]) : nil
18
+ @scope = args.fetch(:scope, :published).to_sym
18
19
 
19
20
  @content_service = args.fetch(:content_service, default_content_service)
20
21
 
@@ -34,7 +35,8 @@ module Dradis
34
35
  @content ||= Dradis::Plugins::ContentService::Base.new(
35
36
  logger: logger,
36
37
  plugin: plugin,
37
- project: project
38
+ project: project,
39
+ scope: scope
38
40
  )
39
41
  end
40
42
 
@@ -7,7 +7,7 @@ module Dradis
7
7
 
8
8
  module VERSION
9
9
  MAJOR = 4
10
- MINOR = 7
10
+ MINOR = 9
11
11
  TINY = 0
12
12
  PRE = nil
13
13
 
@@ -0,0 +1,30 @@
1
+ module Dradis::Plugins::Settings::Adapters
2
+ class Db
3
+ def initialize(namespace)
4
+ @namespace = namespace.to_s
5
+ end
6
+
7
+ def delete(key)
8
+ Configuration.find_by(name: namespaced_key(key)).destroy
9
+ end
10
+
11
+ def exists?(key)
12
+ Configuration.exists?(name: namespaced_key(key))
13
+ end
14
+
15
+ def read(key)
16
+ Configuration.find_by(name: namespaced_key(key))&.value
17
+ end
18
+
19
+ def write(key, value)
20
+ db_setting = Configuration.find_or_create_by(name: namespaced_key(key))
21
+ db_setting.update_attribute(:value, value)
22
+ end
23
+
24
+ private
25
+
26
+ def namespaced_key(key)
27
+ [@namespace, key.to_s.underscore].join(':')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,58 @@
1
+ module Dradis::Plugins::Settings::Adapters
2
+ class EncryptedConfiguration
3
+ attr_writer :config_path
4
+
5
+ def initialize(namespace)
6
+ @namespace = namespace
7
+ end
8
+
9
+ def delete(key)
10
+ if exists?(key)
11
+ configuration.config[@namespace].delete(key)
12
+ configuration.write(configuration.config.to_yaml)
13
+ end
14
+ end
15
+
16
+ def exists?(key)
17
+ !!configuration.config[@namespace]&.key?(key)
18
+ end
19
+
20
+ def read(key)
21
+ configuration.config.fetch(@namespace, {}).fetch(key, nil)
22
+ end
23
+
24
+ def write(key, value)
25
+ configuration.config[@namespace] ||= {}
26
+ configuration.config[@namespace][key] = value
27
+ configuration.write(configuration.config.to_yaml)
28
+ end
29
+
30
+ def key_path=(string_or_pathname)
31
+ @key_path = Pathname.new(string_or_pathname)
32
+ end
33
+
34
+ private
35
+ def config_path
36
+ @config_path ||= Rails.root.join('config', 'shared', 'dradis-plugins.yml.enc')
37
+ end
38
+
39
+ def configuration
40
+ @configuration ||= begin
41
+ create_key unless key_path.exist?
42
+
43
+ ActiveSupport::EncryptedConfiguration.new(
44
+ config_path: config_path, key_path: key_path,
45
+ env_key: 'RAILS_MASTER_KEY', raise_if_missing_key: true
46
+ )
47
+ end
48
+ end
49
+
50
+ def create_key
51
+ File.write(key_path, ActiveSupport::EncryptedConfiguration.generate_key)
52
+ end
53
+
54
+ def key_path
55
+ @key_path ||= Rails.root.join('config', 'shared', 'dradis-plugins.key')
56
+ end
57
+ end
58
+ end
@@ -2,10 +2,11 @@ module Dradis::Plugins
2
2
  class Settings
3
3
  attr_reader :namespace
4
4
 
5
- def initialize(namespace)
5
+ def initialize(namespace, adapter: :db)
6
6
  @namespace = namespace
7
7
  @dirty_options ||= {}
8
8
  @default_options ||= { enabled: true }.with_indifferent_access
9
+ assign_adapter(adapter)
9
10
  end
10
11
 
11
12
  def respond_to?(name)
@@ -16,14 +17,18 @@ module Dradis::Plugins
16
17
  @default_options.except(:enabled).map do |key, value|
17
18
  {
18
19
  name: key.to_sym,
19
- value: value = dirty_or_db_setting_or_default(key.to_sym),
20
+ value: value = dirty_or_stored_or_default(key.to_sym),
20
21
  default: is_default?(key, value)
21
22
  }
22
23
  end.sort_by{ |o| o[:name] }
23
24
  end
24
25
 
25
26
  def save
26
- @dirty_options.reject{ |k, v| v.present? && v == db_setting(k) }.each{ |k, v| write_to_db(k, v) }
27
+ @dirty_options.reject do |k, v|
28
+ v.present? && v == read(k)
29
+ end.each do |k, v|
30
+ write(k, v)
31
+ end
27
32
  end
28
33
 
29
34
  def update_settings(opts = {})
@@ -36,7 +41,7 @@ module Dradis::Plugins
36
41
  def reset_defaults!
37
42
  @dirty_options = {}
38
43
  @default_options.each do |key, value|
39
- Configuration.where(name: namespaced_key(key)).each(&:destroy)
44
+ delete(key) if exists?(key)
40
45
  end
41
46
  end
42
47
 
@@ -45,6 +50,8 @@ module Dradis::Plugins
45
50
  end
46
51
 
47
52
  private
53
+ attr_reader :adapter
54
+ delegate :delete, :exists?, :read, :write, to: :adapter
48
55
 
49
56
  # ---------------------------------------------------- Method missing magic
50
57
  def method_missing(name, *args, &blk)
@@ -53,39 +60,33 @@ module Dradis::Plugins
53
60
  elsif name.to_s =~ /=$/
54
61
  @dirty_options[$`.to_sym] = args.first
55
62
  elsif @default_options.key?(name)
56
- dirty_or_db_setting_or_default(name)
63
+ dirty_or_stored_or_default(name)
57
64
  else
58
65
  super
59
66
  end
60
67
  end
61
68
  # --------------------------------------------------- /Method missing magic
62
69
 
63
- def write_to_db(key, value)
64
- db_setting = Configuration.find_or_create_by(name: namespaced_key(key))
65
- db_setting.update_attribute(:value, value)
66
- end
67
-
68
-
69
- def db_setting(key)
70
- Configuration.where(name: namespaced_key(key)).first.value rescue nil
70
+ def assign_adapter(name)
71
+ adapters = { db: Adapters::Db, encrypted_configuration: Adapters::EncryptedConfiguration }
72
+ if adapters.key?(name)
73
+ @adapter = adapters[name].new(namespace)
74
+ else
75
+ raise ArgumentError
76
+ end
71
77
  end
72
78
 
73
79
  # This method looks up in the configuration repository DB to see if the
74
80
  # user has provided a value for the given setting. If not, the default
75
81
  # value is returned.
76
- def dirty_or_db_setting_or_default(key)
82
+ def dirty_or_stored_or_default(key)
77
83
  if @dirty_options.key?(key)
78
84
  @dirty_options[key]
79
- elsif Configuration.exists?(name: namespaced_key(key))
80
- db_setting(key)
85
+ elsif exists?(key)
86
+ read(key)
81
87
  else
82
88
  @default_options[key]
83
89
  end
84
90
  end
85
-
86
- # Builds namespaced key
87
- def namespaced_key(key)
88
- [self.namespace.to_s, key.to_s.underscore].join(":")
89
- end
90
91
  end
91
92
  end
@@ -9,7 +9,7 @@ module Dradis
9
9
  end
10
10
 
11
11
  def task_options
12
- @task_options ||= { logger: logger }
12
+ @task_options ||= { logger: logger, state: :published }
13
13
  end
14
14
 
15
15
  def logger
@@ -12,6 +12,7 @@ module Dradis
12
12
  :options,
13
13
  :plugin,
14
14
  :project,
15
+ :state,
15
16
  :template_service
16
17
  )
17
18
 
@@ -22,10 +23,11 @@ module Dradis
22
23
  def initialize(args={})
23
24
  @options = args
24
25
 
25
- @logger = args.fetch(:logger, Rails.logger)
26
- @plugin = args[:plugin] || default_plugin
27
- @project = args.key?(:project_id) ? Project.find(args[:project_id]) : nil
28
26
  @default_user_id = args[:default_user_id] || -1
27
+ @logger = args.fetch(:logger, Rails.logger)
28
+ @plugin = args[:plugin] || default_plugin
29
+ @project = args.key?(:project_id) ? Project.find(args[:project_id]) : nil
30
+ @state = args.fetch(:state, :published)
29
31
 
30
32
  @content_service = args.fetch(:content_service, default_content_service)
31
33
  @template_service = args.fetch(:template_service, default_template_service)
@@ -46,7 +48,8 @@ module Dradis
46
48
  @content ||= Dradis::Plugins::ContentService::Base.new(
47
49
  logger: logger,
48
50
  plugin: plugin,
49
- project: project
51
+ project: project,
52
+ state: state
50
53
  )
51
54
  end
52
55
 
@@ -84,6 +84,8 @@ require 'dradis/plugins/upload'
84
84
  # Common functionality
85
85
  require 'dradis/plugins/configurable'
86
86
  require 'dradis/plugins/settings'
87
+ require 'dradis/plugins/settings/adapters/db'
88
+ require 'dradis/plugins/settings/adapters/encrypted_configuration'
87
89
  require 'dradis/plugins/templates'
88
90
  require 'dradis/plugins/thor'
89
91
  require 'dradis/plugins/thor_helper'
data/spec/engine_spec.rb CHANGED
@@ -13,11 +13,14 @@ describe Dradis::Plugins::Base do
13
13
 
14
14
  describe '#enabled?' do
15
15
  it 'returns default value' do
16
- expect(TestEngine.enabled?).to eq(false)
16
+ expect(TestEngine.enabled?).to eq(true)
17
17
  end
18
18
  end
19
19
  describe '#enable!' do
20
20
  it 'sets enabled to true' do
21
+ TestEngine.settings.enabled = false
22
+ TestEngine.settings.save
23
+
21
24
  expect { TestEngine.enable! }.to change {
22
25
  TestEngine.enabled?
23
26
  }.from(false).to(true)
@@ -25,7 +28,9 @@ describe Dradis::Plugins::Base do
25
28
  end
26
29
  describe '#disable!' do
27
30
  it 'sets enabled to false' do
28
- TestEngine.enable!
31
+ TestEngine.settings.enabled = true
32
+ TestEngine.settings.save
33
+
29
34
  expect { TestEngine.disable! }.to change {
30
35
  TestEngine.enabled?
31
36
  }.from(true).to(false)
@@ -20,7 +20,7 @@ describe Dradis::Plugins::ContentService::Boards do
20
20
  node = create(:node, project: project)
21
21
  node_board = create(:board, node: node, project: project)
22
22
 
23
- boards = service.all_boards
23
+ boards = service.project_boards
24
24
 
25
25
  expect(boards).to include(board)
26
26
  expect(boards).to_not include(node_board)
@@ -0,0 +1,29 @@
1
+ require 'rails_helper'
2
+
3
+ # To run, execute from Dradis Pro main app folder:
4
+ # bin/rspec [dradis-plugins path]/spec/lib/dradis/plugins/content_service/content_blocks_spec.rb
5
+
6
+ describe 'Content Block content service' do
7
+ let(:plugin) { Dradis::Plugins::Nessus }
8
+ let(:plugin_id) { '111' }
9
+ let(:project) { create(:project) }
10
+ let(:service) do
11
+ Dradis::Plugins::ContentService::Base.new(
12
+ plugin: plugin,
13
+ logger: Rails.logger,
14
+ project: project
15
+ )
16
+ end
17
+
18
+ describe '#all_content_blocks' do
19
+ before do
20
+ @draft_content = create_list(:content_block, 10, project: project, state: :draft)
21
+ @review_content = create_list(:content_block, 10, project: project, state: :ready_for_review)
22
+ @published_content = create_list(:content_block, 10, project: project, state: :published)
23
+ end
24
+
25
+ it 'returns only the published content blocks' do
26
+ expect(service.all_content_blocks.to_a).to match_array(@published_content)
27
+ end
28
+ end
29
+ end
@@ -1,11 +1,11 @@
1
1
  require 'rails_helper'
2
2
 
3
- # These specs are coming from engines/dradispro-rules/spec/content_service_spec.rb
4
3
  # To run, execute from Dradis main app folder:
5
4
  # bin/rspec [dradis-plugins path]/spec/lib/dradis/plugins/content_service/issues_spec.rb
6
5
 
7
- describe Dradis::Plugins::ContentService::Base do
8
- let(:plugin) { Dradis::Plugins::Nessus }
6
+ describe 'Issues content service' do
7
+ let(:plugin) { Dradis::Plugins::Nessus }
8
+ let(:plugin_id) { '111' }
9
9
  let(:project) { create(:project) }
10
10
  let(:service) do
11
11
  Dradis::Plugins::ContentService::Base.new(
@@ -17,47 +17,39 @@ describe Dradis::Plugins::ContentService::Base do
17
17
 
18
18
  describe 'Issues' do
19
19
  let(:create_issue) do
20
- service.create_issue_without_callback(id: plugin_id)
20
+ service.create_issue(text: "#[Title]#\nTest Issue\n", id: plugin_id, state: :ready_for_review)
21
21
  end
22
22
 
23
- # Remember: even though we're calling create_issue_without_callback,
24
- # that method will still call issue_cache_with_callback internally.
25
- # So when we store an issue in the issue_cache/finding_cache below,
26
- # it's being stored within an instance of FindingCache, which
27
- # automatically wraps Issues in Findings.
28
-
29
23
  describe 'when the issue already exists in the cache' do
30
- let(:existing_issue) { create(:issue, text: cached_issue_text) }
31
- before { cache.store(existing_issue) }
32
-
33
- it "doesn't create a new issue" do
34
- expect{create_issue}.not_to change{Issue.count}
24
+ before do
25
+ issue = create(:issue, text: "#[Title]#\nTest Issue\n", id: plugin_id)
26
+ service.issue_cache.store("nessus-#{plugin_id}", issue)
35
27
  end
36
28
 
37
- it 'returns the cached issue encapsulated in a finding' do
38
- finding = create_issue
39
- expect(finding).to be_a(Finding)
40
- expect(finding).to eq Finding.from_issue(existing_issue)
29
+ it 'does not create a new issue' do
30
+ expect { create_issue }.not_to change { Issue.count }
41
31
  end
42
32
  end
43
33
 
44
34
  describe "when the issue doesn't already exist in the cache" do
45
35
  it "creates a new Issue containing 'plugin' and 'plugin_id'" do
46
36
  new_issue = nil
47
- expect{new_issue = create_issue}.to change{Issue.count}.by(1)
48
- expect(new_issue.body).to match(/#\[plugin\]#\n*#{plugin_name}/)
49
- expect(new_issue.body).to match(/#\[plugin_id\]#\n*#{plugin_id}/)
37
+ plugin_name = "#{plugin}::Engine".constantize.plugin_name
38
+ expect { new_issue = create_issue }.to change { Issue.count }.by(1)
39
+ expect(new_issue.text).to match(/#\[plugin\]#\n*#{plugin_name}/)
40
+ expect(new_issue.text).to match(/#\[plugin_id\]#\n*#{plugin_id}/)
50
41
  end
42
+ end
51
43
 
52
- it 'returns the new Issue encapsulated in a Finding' do
53
- finding = create_issue
54
- expect(finding).to be_a(Finding)
55
- expect(finding).to eq Finding.from_issue(Issue.last)
44
+ describe '#all_issues' do
45
+ before do
46
+ @draft_issues = create_list(:issue, 10, project: project, state: :draft)
47
+ @review_issues = create_list(:issue, 10, project: project, state: :ready_for_review)
48
+ @published_issues = create_list(:issue, 10, project: project, state: :published)
56
49
  end
57
50
 
58
- it 'adds the new Finding to the cache' do
59
- finding = create_issue
60
- expect(cache[cache_key]).to eq finding
51
+ it 'returns only the published issues' do
52
+ expect(service.all_issues.to_a).to match_array(@published_issues)
61
53
  end
62
54
  end
63
55
  end
@@ -0,0 +1,112 @@
1
+ #
2
+ # This spec must be run from Dradis root dir.
3
+ #
4
+ # Configuration init from:
5
+ # https://github.com/rails/rails/blob/main/activesupport/test/encrypted_configuration_test.rb
6
+ #
7
+ require 'rails_helper'
8
+
9
+ describe Dradis::Plugins::Settings::Adapters::EncryptedConfiguration do
10
+
11
+ subject do
12
+ ec = Dradis::Plugins::Settings::Adapters::EncryptedConfiguration.new(:rspec)
13
+ ec.config_path = @credentials_config_path
14
+ ec.key_path = @credentials_key_path
15
+ ec
16
+ end
17
+
18
+ context 'With an empty config file' do
19
+ before(:all) do
20
+ @tmpdir = Dir.mktmpdir('config-')
21
+ @credentials_config_path = File.join(@tmpdir, 'empty.yml.enc')
22
+ @credentials_key_path = File.join(@tmpdir, 'empty.key')
23
+ end
24
+
25
+ describe '#delete' do
26
+ it 'becomes a no-op' do
27
+ expect { subject.delete(:key) }.to_not raise_error
28
+ end
29
+ end
30
+
31
+ describe '#exists' do
32
+ it 'is always false' do
33
+ expect(subject.exists?(:key)).to be(false)
34
+ expect(subject.exists?(:key2)).to be(false)
35
+ end
36
+ end
37
+
38
+ describe '#read' do
39
+ it 'always returns nil' do
40
+ expect(subject.read(:key)).to eq(nil)
41
+ expect(subject.read(:key2)).to eq(nil)
42
+ end
43
+ end
44
+
45
+ describe '#write' do
46
+ it 'inits the namespace and stores the setting' do
47
+ expect { subject.write(:key, :value) }.to_not raise_error
48
+ expect(File.size(@credentials_config_path)).to_not be(0)
49
+
50
+ File.unlink @credentials_config_path
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'With a working config file' do
56
+ DEFAULT_CONFIG = { rspec: { key: :lorem_ipsum, key2: :dolor_sit } }.to_yaml.freeze
57
+
58
+ before(:all) do
59
+ @tmpdir = Dir.mktmpdir('config-')
60
+ @credentials_config_path = File.join(@tmpdir, 'credentials.yml.enc')
61
+ @credentials_key_path = File.join(@tmpdir, 'master.key')
62
+
63
+ File.write(@credentials_key_path, ActiveSupport::EncryptedConfiguration.generate_key)
64
+
65
+ @credentials = ActiveSupport::EncryptedConfiguration.new(
66
+ config_path: @credentials_config_path, key_path: @credentials_key_path,
67
+ env_key: 'RAILS_MASTER_KEY', raise_if_missing_key: true
68
+ )
69
+
70
+ @credentials.write(DEFAULT_CONFIG)
71
+ end
72
+
73
+ after(:all) do
74
+ FileUtils.rm_rf @tmpdir
75
+ end
76
+
77
+ describe '#delete' do
78
+ it 'removes a value from disk' do
79
+ subject.delete(:key2)
80
+
81
+ @credentials.instance_variable_set('@config', nil)
82
+ expect(@credentials.config[:rspec].key?(:key)).to be(true)
83
+ expect(@credentials.config[:rspec].key?(:key2)).to be(false)
84
+ @credentials.write(DEFAULT_CONFIG)
85
+ end
86
+ end
87
+
88
+ describe '#exists' do
89
+ it 'finds an existing value' do
90
+ expect(subject.exists?(:key)).to be(true)
91
+ end
92
+ it 'detects an inexisting value' do
93
+ expect(subject.exists?(:key3)).to be(false)
94
+ end
95
+ end
96
+
97
+ describe '#read' do
98
+ it 'loads an already existing value' do
99
+ expect(subject.read(:key)).to eq(:lorem_ipsum)
100
+ end
101
+ end
102
+
103
+ describe '#write' do
104
+ it 'stores a value on disk' do
105
+ subject.write(:new_key, :new_value)
106
+ @credentials.instance_variable_set('@config', nil)
107
+ expect(@credentials.config[:rspec][:new_key]).to eq(:new_value)
108
+ @credentials.write(DEFAULT_CONFIG)
109
+ end
110
+ end
111
+ end
112
+ end
@@ -19,7 +19,6 @@ describe Dradis::Plugins::Settings do
19
19
  end
20
20
 
21
21
  it "sets and return default values" do
22
- expect(TestEngine::settings.enabled).to eq(false)
23
22
  expect(TestEngine::settings.host).to eq('localhost')
24
23
  expect(TestEngine::settings.port).to eq(80)
25
24
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dradis-plugins
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.7.0
4
+ version: 4.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Martin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-20 00:00:00.000000000 Z
11
+ date: 2023-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec-rails
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,8 @@ files:
94
94
  - lib/dradis/plugins/import/filters/base.rb
95
95
  - lib/dradis/plugins/import/result.rb
96
96
  - lib/dradis/plugins/settings.rb
97
+ - lib/dradis/plugins/settings/adapters/db.rb
98
+ - lib/dradis/plugins/settings/adapters/encrypted_configuration.rb
97
99
  - lib/dradis/plugins/template_service.rb
98
100
  - lib/dradis/plugins/templates.rb
99
101
  - lib/dradis/plugins/thor.rb
@@ -106,7 +108,9 @@ files:
106
108
  - spec/engine_spec.rb
107
109
  - spec/internal/log/test.log
108
110
  - spec/lib/dradis/plugins/content_service/boards_spec.rb
111
+ - spec/lib/dradis/plugins/content_service/content_blocks_spec.rb
109
112
  - spec/lib/dradis/plugins/content_service/issues_spec.rb
113
+ - spec/lib/dradis/plugins/settings/adapters/encrypted_configuration_spec.rb
110
114
  - spec/settings_spec.rb
111
115
  - spec/spec_helper.rb
112
116
  homepage: http://dradisframework.org
@@ -136,6 +140,8 @@ test_files:
136
140
  - spec/engine_spec.rb
137
141
  - spec/internal/log/test.log
138
142
  - spec/lib/dradis/plugins/content_service/boards_spec.rb
143
+ - spec/lib/dradis/plugins/content_service/content_blocks_spec.rb
139
144
  - spec/lib/dradis/plugins/content_service/issues_spec.rb
145
+ - spec/lib/dradis/plugins/settings/adapters/encrypted_configuration_spec.rb
140
146
  - spec/settings_spec.rb
141
147
  - spec/spec_helper.rb