dradis-plugins 4.8.0 → 4.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cba7a2e144b2d99cb1cb3ed6433424e6e46c0c9b2ac4b92ba44d2d8c18e22a5
4
- data.tar.gz: 63fb037763ed258a8286c01a2430b4c61b8c70a3e79f5bf372f468a679c2dcb6
3
+ metadata.gz: 76e20a999e5f8a6309b837043fc488dc8d7f8f6bafae273482f9f1027078aa04
4
+ data.tar.gz: aa7c0068193b07f847ea8f0ddb6b7a8f2fb4705922ebb3da01df2859837fe4f7
5
5
  SHA512:
6
- metadata.gz: aae6bd486e5d39e78c7cef4731476ec3350a3dd73bd4dfac18061fd3dabd2a9d51a7045fd9c64a967c453000794d1d990a67f4d2ecc3bd77dc3b8646cfdd2039
7
- data.tar.gz: 861a9ef7afdcc8450f13abde042710e25770c6edd9ed25d860703180a3b280bdcdf0aca4a7a8e780c3e259c529c1c96a21359ecd6c7c7286974365fadad61a5e
6
+ metadata.gz: efcd0183333ddf9271c3ecca1a7c4793bb864c7e6172d46bc1f335e543ecbbfcedc640953230d976c5ba9e052df2988a5077921f78a61f95e6fa188782f44357
7
+ data.tar.gz: 0c73436e1dd6d733a37fe4ccf10519f0d710137eab88eb6170fc44756d993c142372751e7f41dbc3ca5798ae6c2494d6d1829e9ba5d68cd4b1ed341fa7c92467
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ v4.9.0 (June 2023)
2
+ - Fix deduplication of findings
3
+ - Store engine settings encrypted
4
+
1
5
  v4.8.0 (April 2023)
2
6
  - Add support for issue and content block states
3
7
 
@@ -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', '>= 2.2.33'
24
- spec.add_development_dependency 'rake', '>= 12.3.3'
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
@@ -76,7 +76,7 @@ module Dradis::Plugins::ContentService
76
76
  # the issue library cache has been initialized.
77
77
  def issue_cache
78
78
  @issue_cache ||= begin
79
- issues_map = all_issues.map do |issue|
79
+ issues_map = project.issues.map do |issue|
80
80
  cache_key = [
81
81
  issue.fields['plugin'],
82
82
  issue.fields['plugin_id']
@@ -7,7 +7,7 @@ module Dradis
7
7
 
8
8
  module VERSION
9
9
  MAJOR = 4
10
- MINOR = 8
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
@@ -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,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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dradis-plugins
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.0
4
+ version: 4.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Martin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-12 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
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.2.33
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: 2.2.33
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: 12.3.3
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: 12.3.3
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
@@ -108,13 +110,14 @@ files:
108
110
  - spec/lib/dradis/plugins/content_service/boards_spec.rb
109
111
  - spec/lib/dradis/plugins/content_service/content_blocks_spec.rb
110
112
  - spec/lib/dradis/plugins/content_service/issues_spec.rb
113
+ - spec/lib/dradis/plugins/settings/adapters/encrypted_configuration_spec.rb
111
114
  - spec/settings_spec.rb
112
115
  - spec/spec_helper.rb
113
116
  homepage: http://dradisframework.org
114
117
  licenses:
115
118
  - GPL-2
116
119
  metadata: {}
117
- post_install_message:
120
+ post_install_message:
118
121
  rdoc_options: []
119
122
  require_paths:
120
123
  - lib
@@ -129,8 +132,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
132
  - !ruby/object:Gem::Version
130
133
  version: '0'
131
134
  requirements: []
132
- rubygems_version: 3.3.7
133
- signing_key:
135
+ rubygems_version: 3.1.4
136
+ signing_key:
134
137
  specification_version: 4
135
138
  summary: Plugin manager for the Dradis Framework project.
136
139
  test_files:
@@ -139,5 +142,6 @@ test_files:
139
142
  - spec/lib/dradis/plugins/content_service/boards_spec.rb
140
143
  - spec/lib/dradis/plugins/content_service/content_blocks_spec.rb
141
144
  - spec/lib/dradis/plugins/content_service/issues_spec.rb
145
+ - spec/lib/dradis/plugins/settings/adapters/encrypted_configuration_spec.rb
142
146
  - spec/settings_spec.rb
143
147
  - spec/spec_helper.rb