chamber 2.14.3 → 3.0.0rc2

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: '08e636d1674a305c9d330e9adf5be147b1e5c2d2c57f131da98a216e3d3b3111'
4
- data.tar.gz: 7848e6ca2e2e4de843eedc65f9ca5315c18e71f9a8a2ba67a37c0ea46930a482
3
+ metadata.gz: 9de7c74ea902d381006bd6b5f05bae3680d1beef940ae75e483f30c923bc310f
4
+ data.tar.gz: b6f45eb5b668a5964e898ffb4caa5b9a3e9bc227736dd0e687e257cff0c99f84
5
5
  SHA512:
6
- metadata.gz: 8337ba8c0c7cc899f40bb712a455e5ee56e878ed11f6258e0917863acf194b4cac1a4b11ff087a4c72ed7e5550972fc2d097dafd5b26492a40c8094bd33a744a
7
- data.tar.gz: 27b49b8592d343b050491f2a2d22cbd69323989ac031abc9d6a2bf375a30887cd16580d9c76259a4475c9f42d6603aa73769754b454bbfa55bac98e493ae9c3b
6
+ metadata.gz: b1ab7fedfaf6cb26ab3e97402966368f3e686751ca76e441a7d9db64b7fe354a289ac4ac330cac806fb7960f3b4750c1ce4f7799e548c4f0f549ee57826e8552
7
+ data.tar.gz: 64cfa0683ca78d71cd620e38e60c4d2c25683c5217d74858995b2ee65eda704f7d2aca9395451ac743424bd75b8974ee088ed3563e192be5ab057f49ad458165
checksums.yaml.gz.sig CHANGED
Binary file
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'thor'
4
- require 'chamber/core_ext/hash'
5
4
  require 'chamber/commands/cloud/clear'
6
5
  require 'chamber/commands/cloud/push'
7
6
  require 'chamber/commands/cloud/pull'
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'thor'
4
- require 'chamber/core_ext/hash'
5
4
  require 'chamber/commands/cloud/clear'
6
5
  require 'chamber/commands/cloud/push'
7
6
  require 'chamber/commands/cloud/pull'
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'thor'
4
- require 'chamber/core_ext/hash'
5
4
  require 'chamber/rubinius_fix'
6
5
  require 'chamber/binary/travis'
7
6
  require 'chamber/binary/heroku'
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'thor'
4
- require 'chamber/core_ext/hash'
5
4
  require 'chamber/commands/travis/secure'
6
5
 
7
6
  module Chamber
@@ -194,7 +194,7 @@ class Initialize < Chamber::Commands::Base
194
194
  .chamber*.enc.pass
195
195
  !.chamber*.pub.pem
196
196
  }.each do |pattern|
197
- unless gitignore_contents =~ Regexp.new(Regexp.escape(pattern))
197
+ unless gitignore_contents&.match?(Regexp.new(Regexp.escape(pattern)))
198
198
  shell.append_to_file gitignore_filepath, "#{pattern}\n"
199
199
  end
200
200
  end
@@ -2,55 +2,41 @@
2
2
 
3
3
  require 'base64'
4
4
 
5
+ require 'chamber/errors/disallowed_class'
6
+
5
7
  module Chamber
6
8
  module EncryptionMethods
7
9
  class PublicKey
8
- def self.encrypt(_key, value, encryption_key)
10
+ def self.encrypt(_settings_key, value, encryption_key)
9
11
  value = YAML.dump(value)
10
12
  encrypted_string = encryption_key.public_encrypt(value)
11
13
 
12
14
  Base64.strict_encode64(encrypted_string)
13
15
  end
14
16
 
15
- def self.decrypt(_key, value, decryption_key)
16
- if decryption_key.nil?
17
- value
18
- else
19
- decoded_string = Base64.strict_decode64(value)
20
- unencrypted_value = decryption_key.private_decrypt(decoded_string)
21
-
22
- begin
23
- _unserialized_value = begin
24
- YAML.safe_load(unencrypted_value,
25
- aliases: true,
26
- permitted_classes: [
27
- ::Date,
28
- ::Time,
29
- ::Regexp,
30
- ])
31
- rescue ::Psych::DisallowedClass => error
32
- warn <<-HEREDOC
33
- WARNING: Recursive data structures (complex classes) being loaded from Chamber
34
- has been deprecated and will be removed in 3.0.
35
-
36
- See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes
37
- for full details.
38
-
39
- #{error.message}
40
-
41
- Called from: '#{caller.to_a[8]}'
42
- HEREDOC
43
-
44
- if YAML.respond_to?(:unsafe_load)
45
- YAML.unsafe_load(unencrypted_value)
46
- else
47
- YAML.load(unencrypted_value)
48
- end
49
- end
50
- rescue TypeError
51
- unencrypted_value
52
- end
53
- end
17
+ def self.decrypt(_settings_key, value, decryption_key)
18
+ return value if decryption_key.nil?
19
+
20
+ decoded_string = ::Base64.strict_decode64(value)
21
+ unencrypted_value = decryption_key.private_decrypt(decoded_string)
22
+
23
+ ::YAML.safe_load(unencrypted_value,
24
+ aliases: true,
25
+ permitted_classes: [
26
+ ::Date,
27
+ ::Time,
28
+ ::Regexp,
29
+ ])
30
+ rescue ::Psych::DisallowedClass => error
31
+ raise ::Chamber::Errors::DisallowedClass, <<~HEREDOC
32
+ #{error.message}
33
+
34
+ You attempted to load a class instance via your Chamber settings that is not allowed.
35
+
36
+ See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes for full details.
37
+ HEREDOC
38
+ rescue ::TypeError
39
+ unencrypted_value
54
40
  end
55
41
  end
56
42
  end
@@ -16,7 +16,7 @@ class Ssl
16
16
  \z
17
17
  /x.freeze
18
18
 
19
- def self.encrypt(_key, value, encryption_keys) # rubocop:disable Metrics/AbcSize
19
+ def self.encrypt(_settings_key, value, encryption_keys) # rubocop:disable Metrics/AbcSize
20
20
  value = YAML.dump(value)
21
21
  cipher = OpenSSL::Cipher.new('AES-128-CBC')
22
22
  cipher.encrypt
@@ -35,64 +35,46 @@ class Ssl
35
35
  Base64.strict_encode64(encrypted_data)
36
36
  end
37
37
 
38
- def self.decrypt(key, value, decryption_keys) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
39
- if decryption_keys.nil?
40
- value
41
- else
42
- key, iv, decoded_string = value
43
- .match(LARGE_DATA_STRING_PATTERN)
44
- .captures
45
- .map do |part|
46
- Base64.strict_decode64(part)
47
- end
48
- key = decryption_keys.private_decrypt(key)
38
+ def self.decrypt(_settings_key, value, decryption_keys) # rubocop:disable Metrics/AbcSize
39
+ return value if decryption_keys.nil?
49
40
 
50
- cipher_dec = OpenSSL::Cipher.new('AES-128-CBC')
51
-
52
- cipher_dec.decrypt
41
+ key, iv, decoded_string = value
42
+ .match(LARGE_DATA_STRING_PATTERN)
43
+ .captures
44
+ .map do |part|
45
+ ::Base64.strict_decode64(part)
46
+ end
47
+ key = decryption_keys.private_decrypt(key)
53
48
 
54
- cipher_dec.key = key
55
- cipher_dec.iv = iv
49
+ cipher_dec = ::OpenSSL::Cipher.new('AES-128-CBC')
56
50
 
57
- begin
58
- unencrypted_value = cipher_dec.update(decoded_string) + cipher_dec.final
59
- rescue OpenSSL::Cipher::CipherError
60
- raise Chamber::Errors::DecryptionFailure,
61
- 'A decryption error occurred. It was probably due to invalid key data.'
62
- end
51
+ cipher_dec.decrypt
63
52
 
64
- begin
65
- _unserialized_value = begin
66
- YAML.safe_load(unencrypted_value,
67
- aliases: true,
68
- permitted_classes: [
69
- ::Date,
70
- ::Time,
71
- ::Regexp,
72
- ])
73
- rescue ::Psych::DisallowedClass => error
74
- warn <<-HEREDOC
75
- WARNING: Recursive data structures (complex classes) being loaded from Chamber
76
- has been deprecated and will be removed in 3.0.
53
+ cipher_dec.key = key
54
+ cipher_dec.iv = iv
77
55
 
78
- See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes
79
- for full details.
56
+ unencrypted_value = cipher_dec.update(decoded_string) + cipher_dec.final
80
57
 
81
- #{error.message}
58
+ ::YAML.safe_load(unencrypted_value,
59
+ aliases: true,
60
+ permitted_classes: [
61
+ ::Date,
62
+ ::Time,
63
+ ::Regexp,
64
+ ])
65
+ rescue ::OpenSSL::Cipher::CipherError
66
+ raise ::Chamber::Errors::DecryptionFailure,
67
+ 'A decryption error occurred. It was probably due to invalid key data.'
68
+ rescue ::Psych::DisallowedClass => error
69
+ raise ::Chamber::Errors::DisallowedClass, <<~HEREDOC
70
+ #{error.message}
82
71
 
83
- Called from: '#{caller.to_a[8]}'
84
- HEREDOC
72
+ You attempted to load a class instance via your Chamber settings that is not allowed.
85
73
 
86
- if YAML.respond_to?(:unsafe_load)
87
- YAML.unsafe_load(unencrypted_value)
88
- else
89
- YAML.load(unencrypted_value)
90
- end
91
- end
92
- rescue TypeError
93
- unencrypted_value
94
- end
95
- end
74
+ See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes for full details.
75
+ HEREDOC
76
+ rescue ::TypeError
77
+ unencrypted_value
96
78
  end
97
79
  end
98
80
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chamber
4
+ module Errors
5
+ class DisallowedClass < ::Psych::DisallowedClass
6
+ end
7
+ end
8
+ end
data/lib/chamber/file.rb CHANGED
@@ -139,38 +139,26 @@ class File < Pathname
139
139
  @secure_prefix_pattern ||= Regexp.escape(secure_prefix)
140
140
  end
141
141
 
142
- def file_contents_hash # rubocop:disable Metrics/CyclomaticComplexity
142
+ def file_contents_hash
143
143
  file_contents = read
144
- erb_result = ERB.new(file_contents).result
144
+ erb_result = ::ERB.new(file_contents).result
145
145
 
146
- begin
147
- YAML.safe_load(erb_result,
146
+ ::YAML.safe_load(erb_result,
148
147
  aliases: true,
149
148
  permitted_classes: [
150
149
  ::Date,
151
150
  ::Time,
152
151
  ::Regexp,
153
152
  ]) || {}
154
- rescue ::Psych::DisallowedClass => error
155
- warn <<-HEREDOC
156
- WARNING: Recursive data structures (complex classes) being loaded from Chamber
157
- has been deprecated and will be removed in 3.0.
153
+ rescue ::Psych::DisallowedClass => error
154
+ raise ::Chamber::Errors::DisallowedClass, <<~HEREDOC
155
+ #{error.message}
158
156
 
159
- See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes
160
- for full details.
157
+ You attempted to load a class instance via your Chamber settings that is not allowed.
161
158
 
162
- #{error.message}
163
-
164
- Called from: '#{caller.to_a[2]}'
165
- HEREDOC
166
-
167
- if YAML.respond_to?(:unsafe_load)
168
- YAML.unsafe_load(erb_result) || {}
169
- else
170
- YAML.load(erb_result) || {}
171
- end
172
- end
173
- rescue Errno::ENOENT
159
+ See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes for full details.
160
+ HEREDOC
161
+ rescue ::Errno::ENOENT
174
162
  {}
175
163
  end
176
164
  end
@@ -42,13 +42,13 @@ class Signature
42
42
  end
43
43
 
44
44
  def write
45
- signature_filename.write(<<-HEREDOC, 0, mode: 'w+')
46
- Signed By: #{signature_name}
47
- Signed At: #{Time.now.utc.iso8601}
45
+ signature_filename.write(<<~HEREDOC, 0, mode: 'w+')
46
+ Signed By: #{signature_name}
47
+ Signed At: #{Time.now.utc.iso8601}
48
48
 
49
- #{SIGNATURE_HEADER}
50
- #{encoded_signature}
51
- #{SIGNATURE_FOOTER}
49
+ #{SIGNATURE_HEADER}
50
+ #{encoded_signature}
51
+ #{SIGNATURE_FOOTER}
52
52
  HEREDOC
53
53
  end
54
54
 
@@ -2,16 +2,18 @@
2
2
 
3
3
  require 'openssl'
4
4
  require 'base64'
5
- require 'hashie/mash'
6
5
  require 'yaml'
7
6
  require 'chamber/encryption_methods/public_key'
8
7
  require 'chamber/encryption_methods/ssl'
9
8
  require 'chamber/encryption_methods/none'
10
9
  require 'chamber/errors/decryption_failure'
10
+ require 'chamber/refinements/deep_dup'
11
11
 
12
12
  module Chamber
13
13
  module Filters
14
14
  class DecryptionFilter
15
+ using ::Chamber::Refinements::DeepDup
16
+
15
17
  BASE64_STRING_PATTERN = %r{\A[A-Za-z0-9+/]{342}==\z}.freeze
16
18
  LARGE_DATA_STRING_PATTERN = %r{
17
19
  \A # Beginning of String
@@ -34,8 +36,8 @@ class DecryptionFilter
34
36
  attr_reader :decryption_keys
35
37
 
36
38
  def initialize(data:, secure_key_prefix:, decryption_keys: {}, **_args)
37
- self.decryption_keys = decryption_keys || {}
38
- self.data = data.dup
39
+ self.decryption_keys = (decryption_keys || {}).transform_keys(&:to_s)
40
+ self.data = data.deep_dup
39
41
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
40
42
  end
41
43
 
@@ -46,7 +48,7 @@ class DecryptionFilter
46
48
  protected
47
49
 
48
50
  def execute(raw_data = data)
49
- settings = Hashie::Mash.new
51
+ settings = {}
50
52
 
51
53
  raw_data.each_pair do |key, value|
52
54
  settings[key] = if value.respond_to? :each_pair
@@ -75,21 +77,17 @@ class DecryptionFilter
75
77
 
76
78
  private
77
79
 
78
- # rubocop:disable Style/RedundantBegin
79
80
  def decrypt(key, value)
80
81
  method = decryption_method(value)
81
82
 
82
83
  decryption_keys.each do |decryption_key|
83
- begin
84
- return method.decrypt(key, value, decryption_key)
85
- rescue OpenSSL::PKey::RSAError
86
- next
87
- end
84
+ return method.decrypt(key, value, decryption_key)
85
+ rescue OpenSSL::PKey::RSAError
86
+ next
88
87
  end
89
88
 
90
89
  value
91
90
  end
92
- # rubocop:enable Style/RedundantBegin
93
91
 
94
92
  def decryption_method(value)
95
93
  if value.is_a?(::String)
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openssl'
4
- require 'hashie/mash'
5
4
  require 'yaml'
6
5
  require 'chamber/encryption_methods/public_key'
7
6
  require 'chamber/encryption_methods/ssl'
8
7
  require 'chamber/encryption_methods/none'
8
+ require 'chamber/refinements/deep_dup'
9
9
 
10
10
  module Chamber
11
11
  module Filters
12
12
  class EncryptionFilter
13
+ using ::Chamber::Refinements::DeepDup
14
+
13
15
  BASE64_STRING_PATTERN = %r{\A[A-Za-z0-9+/]{342}==\z}.freeze
14
16
  BASE64_SUBSTRING_PATTERN = %r{[A-Za-z0-9+/#]*={0,2}}.freeze
15
17
  LARGE_DATA_STRING_PATTERN = /
@@ -27,8 +29,8 @@ class EncryptionFilter
27
29
  attr_reader :encryption_keys
28
30
 
29
31
  def initialize(data:, secure_key_prefix:, encryption_keys: {}, **_args)
30
- self.encryption_keys = encryption_keys || {}
31
- self.data = data.dup
32
+ self.encryption_keys = (encryption_keys || {}).transform_keys(&:to_s)
33
+ self.data = data.deep_dup
32
34
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
33
35
  end
34
36
 
@@ -39,7 +41,7 @@ class EncryptionFilter
39
41
  protected
40
42
 
41
43
  def execute(raw_data = data, namespace = nil)
42
- raw_data.each_with_object(Hashie::Mash.new) do |(key, value), settings|
44
+ raw_data.each_with_object({}) do |(key, value), settings|
43
45
  settings[key] = if value.respond_to? :each_pair
44
46
  execute(value, namespace || key)
45
47
  elsif key.match(secure_key_token)
@@ -51,7 +53,7 @@ class EncryptionFilter
51
53
  end
52
54
 
53
55
  def encryption_keys=(other)
54
- @encryption_keys = other.each_with_object({}) do |(namespace, keyish), memo|
56
+ @encryption_keys = other.each_with_object({}) do |(namespace, keyish), memo| # rubocop:disable Style/HashTransformValues
55
57
  memo[namespace] = if keyish.is_a?(OpenSSL::PKey::RSA)
56
58
  keyish
57
59
  elsif ::File.readable?(::File.expand_path(keyish))
@@ -67,7 +69,7 @@ class EncryptionFilter
67
69
 
68
70
  def encrypt(namespace, key, value)
69
71
  method = encryption_method(value)
70
- encryption_key = encryption_keys[namespace] || encryption_keys[:__default]
72
+ encryption_key = encryption_keys[namespace] || encryption_keys['__default']
71
73
 
72
74
  return value unless encryption_key
73
75
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'yaml'
4
- require 'hashie/mash'
5
4
 
6
5
  require 'chamber/errors/environment_conversion'
7
6
 
@@ -122,7 +121,7 @@ class EnvironmentFilter
122
121
  private
123
122
 
124
123
  def with_environment(settings, parent_keys, hash_block, value_block)
125
- environment_hash = Hashie::Mash.new
124
+ environment_hash = {}
126
125
 
127
126
  settings.each_pair do |key, value|
128
127
  environment_key = key.to_s.gsub(secure_key_token, '')
@@ -170,13 +169,13 @@ class EnvironmentFilter
170
169
  environment_value
171
170
  end
172
171
  rescue ArgumentError
173
- raise Chamber::Errors::EnvironmentConversion, <<-HEREDOC
174
- We attempted to convert '#{environment_key}' from '#{environment_value}' to a '#{settings_value.class.name}'.
172
+ raise Chamber::Errors::EnvironmentConversion, <<~HEREDOC
173
+ We attempted to convert '#{environment_key}' from '#{environment_value}' to a '#{settings_value.class.name}'.
175
174
 
176
- Unfortunately, this did not go as planned. Please either verify that your value is convertable
177
- or change the original YAML value to be something more generic (like a String).
175
+ Unfortunately, this did not go as planned. Please either verify that your value is convertable
176
+ or change the original YAML value to be something more generic (like a String).
178
177
 
179
- For more information, see https://github.com/thekompanee/chamber/wiki/Environment-Variable-Coercions
178
+ For more information, see https://github.com/thekompanee/chamber/wiki/Environment-Variable-Coercions
180
179
  HEREDOC
181
180
  end
182
181
  end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'chamber/errors/decryption_failure'
4
+ require 'chamber/refinements/deep_dup'
4
5
 
5
6
  module Chamber
6
7
  module Filters
7
8
  class FailedDecryptionFilter
9
+ using ::Chamber::Refinements::DeepDup
10
+
8
11
  BASE64_STRING_PATTERN = %r{\A[A-Za-z0-9+/]{342}==\z}.freeze
9
12
 
10
13
  def self.execute(**args)
@@ -15,7 +18,7 @@ class FailedDecryptionFilter
15
18
  :secure_key_token
16
19
 
17
20
  def initialize(data:, secure_key_prefix:, **_args)
18
- self.data = data.dup
21
+ self.data = data.deep_dup
19
22
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
20
23
  end
21
24
 
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'hashie/mash'
4
3
  require 'chamber/filters/secure_filter'
5
4
 
6
5
  module Chamber
@@ -22,7 +21,7 @@ class InsecureFilter < SecureFilter
22
21
 
23
22
  def execute(raw_data = data) # rubocop:disable Metrics/CyclomaticComplexity
24
23
  securable_settings = super
25
- settings = Hashie::Mash.new
24
+ settings = {}
26
25
 
27
26
  securable_settings.each_pair do |key, value|
28
27
  value = if value.respond_to? :each_pair
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'hashie/mash'
3
+ require 'chamber/refinements/deep_dup'
4
+ require 'chamber/refinements/hash'
4
5
 
5
6
  module Chamber
6
7
  module Filters
7
8
  class NamespaceFilter
9
+ using ::Chamber::Refinements::DeepDup
10
+ using ::Chamber::Refinements::Hash
11
+
8
12
  def self.execute(**args)
9
13
  new(**args).__send__(:execute)
10
14
  end
@@ -13,26 +17,24 @@ class NamespaceFilter
13
17
  :namespaces
14
18
 
15
19
  def initialize(data:, namespaces:, **_args)
16
- self.data = Hashie::Mash.new(data)
20
+ self.data = data.deep_dup
17
21
  self.namespaces = namespaces
18
22
  end
19
23
 
20
24
  protected
21
25
 
22
26
  def execute
23
- if data_is_namespaced?
24
- namespaces.each_with_object(Hashie::Mash.new) do |namespace, filtered_data|
25
- filtered_data.merge!(data[namespace]) if data[namespace]
26
- end
27
- else
28
- Hashie::Mash.new(data)
27
+ return data unless data_is_namespaced?
28
+
29
+ namespaces.each_with_object({}) do |namespace, filtered_data|
30
+ filtered_data.deep_merge!(data[namespace]) if data[namespace]
29
31
  end
30
32
  end
31
33
 
32
34
  private
33
35
 
34
36
  def data_is_namespaced?
35
- @data_is_namespaced ||= data.keys.any? { |key| namespaces.include? key.to_s }
37
+ @data_is_namespaced ||= data.keys.any? { |key| namespaces.include?(key.to_s) }
36
38
  end
37
39
  end
38
40
  end
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'hashie/mash'
3
+ require 'chamber/refinements/deep_dup'
4
4
 
5
5
  module Chamber
6
6
  module Filters
7
7
  class SecureFilter
8
+ using ::Chamber::Refinements::DeepDup
9
+
8
10
  def self.execute(**args)
9
11
  new(**args).__send__(:execute)
10
12
  end
@@ -13,14 +15,14 @@ class SecureFilter
13
15
  :secure_key_token
14
16
 
15
17
  def initialize(data:, secure_key_prefix:, **_args)
16
- self.data = Hashie::Mash.new(data)
18
+ self.data = data.deep_dup
17
19
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
18
20
  end
19
21
 
20
22
  protected
21
23
 
22
24
  def execute(raw_data = data)
23
- settings = Hashie::Mash.new
25
+ settings = {}
24
26
 
25
27
  raw_data.each_pair do |key, value|
26
28
  secure_value = if value.respond_to? :each_pair
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'hashie/mash'
3
+ require 'chamber/refinements/deep_dup'
4
4
 
5
5
  module Chamber
6
6
  module Filters
7
7
  class TranslateSecureKeysFilter
8
+ using ::Chamber::Refinements::DeepDup
9
+
8
10
  def self.execute(**args)
9
11
  new(**args).__send__(:execute)
10
12
  end
@@ -13,14 +15,14 @@ class TranslateSecureKeysFilter
13
15
  :secure_key_token
14
16
 
15
17
  def initialize(data:, secure_key_prefix:, **_args)
16
- self.data = data.dup
18
+ self.data = data.deep_dup
17
19
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
18
20
  end
19
21
 
20
22
  protected
21
23
 
22
24
  def execute(raw_data = data)
23
- settings = Hashie::Mash.new
25
+ settings = {}
24
26
 
25
27
  raw_data.each_pair do |key, value|
26
28
  value = execute(value) if value.respond_to? :each_pair
@@ -92,15 +92,5 @@ class Instance
92
92
  )
93
93
  .to_hash
94
94
  end
95
-
96
- def method_missing(name, *args)
97
- return settings.public_send(name, *args) if settings.respond_to?(name)
98
-
99
- super
100
- end
101
-
102
- def respond_to_missing?(name, include_private = false)
103
- settings.respond_to?(name, include_private)
104
- end
105
95
  end
106
96
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chamber
4
+ module Refinements
5
+ module DeepDup
6
+ refine ::Array do
7
+ def deep_dup
8
+ map { |i| i.respond_to?(:deep_dup) ? i.deep_dup : i.dup }
9
+ end
10
+ end
11
+
12
+ refine ::Object do
13
+ def deep_dup
14
+ dup
15
+ end
16
+ end
17
+
18
+ refine ::Hash do
19
+ def deep_dup
20
+ dup.tap do |hash|
21
+ each_pair do |key, value|
22
+ if key.frozen? && key.is_a?(::String)
23
+ hash[key] = value.deep_dup
24
+ else
25
+ hash.delete(key)
26
+ hash[key.deep_dup] = value.deep_dup
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -9,8 +9,7 @@ class Enumerable
9
9
  case object
10
10
  when ::Hash
11
11
  object.each do |(key, value)|
12
- # fail ::Chamber::Errors::NonConformingKey unless key == yield(key)
13
- warn "WARNING: Non-String settings keys are deprecated and will be removed in Chamber 3.0. You attempted to access the '#{key}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#all-settings-keys-are-now-stored-as-strings for full details. Called from: '#{caller.to_a.first}'" unless key == yield(key) # rubocop:disable Layout/LineLength
12
+ fail ::Chamber::Errors::NonConformingKey unless key == yield(key)
14
13
 
15
14
  deep_validate_keys(value, &block)
16
15
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chamber
4
+ module Refinements
5
+ module Hash
6
+ refine ::Hash do
7
+ def deep_merge(other_hash, &block)
8
+ dup.deep_merge!(other_hash, &block)
9
+ end
10
+
11
+ def deep_merge!(other_hash, &block)
12
+ merge!(other_hash) do |key, this_val, other_val|
13
+ if this_val.is_a?(::Hash) && other_val.is_a?(::Hash)
14
+ this_val.deep_merge(other_val, &block)
15
+ elsif block
16
+ yield(key, this_val, other_val)
17
+ else
18
+ other_val
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'hashie/mash'
4
3
  require 'chamber/namespace_set'
5
4
  require 'chamber/filters/namespace_filter'
6
5
  require 'chamber/filters/encryption_filter'
@@ -10,13 +9,18 @@ require 'chamber/filters/secure_filter'
10
9
  require 'chamber/filters/translate_secure_keys_filter'
11
10
  require 'chamber/filters/insecure_filter'
12
11
  require 'chamber/filters/failed_decryption_filter'
12
+ require 'chamber/refinements/deep_dup'
13
13
  require 'chamber/refinements/enumerable'
14
+ require 'chamber/refinements/hash'
14
15
 
15
16
  ###
16
17
  # Internal: Represents the base settings storage needed for Chamber.
17
18
  #
18
19
  module Chamber
19
20
  class Settings
21
+ using ::Chamber::Refinements::Hash
22
+ using ::Chamber::Refinements::DeepDup
23
+
20
24
  attr_accessor :decryption_keys,
21
25
  :encryption_keys,
22
26
  :post_filters,
@@ -45,12 +49,12 @@ class Settings
45
49
 
46
50
  ::Chamber::Refinements::Enumerable.deep_validate_keys(settings, &:to_s)
47
51
 
48
- self.decryption_keys = decryption_keys
49
- self.encryption_keys = encryption_keys
50
- self.namespaces = namespaces
52
+ self.decryption_keys = (decryption_keys || {}).transform_keys(&:to_s)
53
+ self.encryption_keys = (encryption_keys || {}).transform_keys(&:to_s)
54
+ self.namespaces = NamespaceSet.new(namespaces)
51
55
  self.post_filters = post_filters
52
56
  self.pre_filters = pre_filters
53
- self.raw_data = settings
57
+ self.raw_data = settings.deep_dup
54
58
  self.secure_key_prefix = secure_key_prefix
55
59
  end
56
60
  # rubocop:enable Metrics/ParameterLists
@@ -113,7 +117,7 @@ class Settings
113
117
  # Returns a Hash
114
118
  #
115
119
  def to_hash
116
- data.to_hash
120
+ data.deep_dup
117
121
  end
118
122
 
119
123
  ###
@@ -205,7 +209,7 @@ class Settings
205
209
  encryption_keys: encryption_keys.any? ? encryption_keys : other_settings.encryption_keys,
206
210
  decryption_keys: decryption_keys.any? ? decryption_keys : other_settings.decryption_keys,
207
211
  namespaces: (namespaces + other_settings.namespaces),
208
- settings: raw_data.merge(other_settings.raw_data),
212
+ settings: raw_data.deep_merge(other_settings.raw_data),
209
213
  )
210
214
  # rubocop:enable Layout/LineLength
211
215
  end
@@ -232,10 +236,9 @@ class Settings
232
236
  end
233
237
 
234
238
  def [](key)
235
- warn "WARNING: Bracket access will require strings instead of symbols in Chamber 3.0. You attempted to access the '#{key}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#removal-of-bracket-indifferent-access for full details. Called from: '#{caller.to_a.first}'" if key.is_a?(::Symbol) # rubocop:disable Layout/LineLength
236
- warn "WARNING: Accessing a non-existent key ('#{key}') with brackets will fail in Chamber 3.0. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#bracket-access-now-fails-on-non-existent-keys for full details. Called from: '#{caller.to_a.first}'" unless data.has_key?(key) # rubocop:disable Layout/LineLength
239
+ fail ::ArgumentError, 'Bracket access with anything other than a String is unsupported.' unless key.is_a?(::String)
237
240
 
238
- data.[](key)
241
+ data.fetch(key)
239
242
  end
240
243
 
241
244
  def dig!(*args)
@@ -275,30 +278,10 @@ class Settings
275
278
  ))
276
279
  end
277
280
 
278
- def method_missing(name, *args)
279
- if data.respond_to?(name)
280
- warn "WARNING: Object notation access is deprecated and will be removed in Chamber 3.0. You attempted to access the '#{name}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#removal-of-object-notation-access for full details. Called from: '#{caller.to_a.first}'" # rubocop:disable Layout/LineLength
281
- warn "WARNING: Predicate methods are deprecated and will be removed in Chamber 3.0. You attempted to access the '#{name}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#removal-of-predicate-accessors for full details. Called from: '#{caller.to_a.first}'" if name.to_s.end_with?('?') # rubocop:disable Layout/LineLength
282
-
283
- data.public_send(name, *args)
284
- else
285
- super
286
- end
287
- end
288
-
289
- def respond_to_missing?(name, include_private = false)
290
- data.respond_to?(name, include_private)
291
- end
292
-
293
281
  protected
294
282
 
295
- def raw_data=(new_raw_data)
296
- @raw_data = Hashie::Mash.new(new_raw_data)
297
- end
298
-
299
- def namespaces=(raw_namespaces)
300
- @namespaces = NamespaceSet.new(raw_namespaces)
301
- end
283
+ attr_writer :namespaces,
284
+ :raw_data
302
285
 
303
286
  # rubocop:disable Naming/MemoizedInstanceVariableName
304
287
  def raw_data
@@ -40,7 +40,7 @@ class Secured < CHAMBER_TYPE_VALUE_SUPERCLASS
40
40
  when Hash
41
41
  value
42
42
  when String
43
- ::ActiveSupport::JSON.decode(value)
43
+ ::JSON.parse(value)
44
44
  when NilClass
45
45
  nil
46
46
  else
@@ -63,10 +63,10 @@ class Secured < CHAMBER_TYPE_VALUE_SUPERCLASS
63
63
  def serialize(value)
64
64
  fail ArgumentError, 'Any attributes encrypted with Chamber must be a Hash' unless value.is_a?(Hash)
65
65
 
66
- ::ActiveSupport::JSON.encode(
67
- Chamber.encrypt(value,
68
- decryption_keys: decryption_keys,
69
- encryption_keys: encryption_keys),
66
+ ::JSON.dump(
67
+ ::Chamber.encrypt(value,
68
+ decryption_keys: decryption_keys,
69
+ encryption_keys: encryption_keys),
70
70
  )
71
71
  end
72
72
  alias type_cast_for_database serialize
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chamber
4
- VERSION = '2.14.3'
4
+ VERSION = '3.0.0rc2'
5
5
  end
data/lib/chamber.rb CHANGED
@@ -11,10 +11,6 @@ module Chamber
11
11
  self.instance = Instance.new(**args)
12
12
  end
13
13
 
14
- def env
15
- instance.settings
16
- end
17
-
18
14
  def instance
19
15
  @instance ||= Instance.new
20
16
  end
@@ -81,29 +77,17 @@ module Chamber
81
77
  instance.to_s(**args)
82
78
  end
83
79
 
84
- def method_missing(name, *args)
85
- return instance.public_send(name, *args) if instance.respond_to?(name)
86
-
87
- super
88
- end
89
-
90
- def respond_to_missing?(name, include_private = false)
91
- instance.respond_to?(name, include_private)
92
- end
93
-
94
80
  module_function :[],
95
81
  :configuration,
96
82
  :decrypt,
97
83
  :dig!,
98
84
  :dig,
99
85
  :encrypt,
100
- :env,
101
86
  :filenames,
102
87
  :files,
103
88
  :instance,
104
89
  :instance=,
105
90
  :load,
106
- :method_missing,
107
91
  :namespaces,
108
92
  :respond_to_missing?,
109
93
  :secure,
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chamber
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.14.3
4
+ version: 3.0.0rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - thekompanee
@@ -38,7 +38,7 @@ cert_chain:
38
38
  ZjvLRaDI6IVoq0skZju//VZLiN6slVhAYYQj0uka/T0DZieabVYDcT4BVpa9M7Gz
39
39
  CDW/VDWjvEEbsCIW0oYhtUrkqE8GLIdrpLUjefOERbS5TslD7lG/MH5k
40
40
  -----END CERTIFICATE-----
41
- date: 2022-03-05 00:00:00.000000000 Z
41
+ date: 2022-03-06 00:00:00.000000000 Z
42
42
  dependencies:
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: thor
@@ -60,20 +60,6 @@ dependencies:
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '2.0'
63
- - !ruby/object:Gem::Dependency
64
- name: hashie
65
- requirement: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: '3.3'
70
- type: :runtime
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- requirements:
74
- - - "~>"
75
- - !ruby/object:Gem::Version
76
- version: '3.3'
77
63
  - !ruby/object:Gem::Dependency
78
64
  name: rspec
79
65
  requirement: !ruby/object:Gem::Requirement
@@ -183,11 +169,11 @@ files:
183
169
  - lib/chamber/commands/verify.rb
184
170
  - lib/chamber/configuration.rb
185
171
  - lib/chamber/context_resolver.rb
186
- - lib/chamber/core_ext/hash.rb
187
172
  - lib/chamber/encryption_methods/none.rb
188
173
  - lib/chamber/encryption_methods/public_key.rb
189
174
  - lib/chamber/encryption_methods/ssl.rb
190
175
  - lib/chamber/errors/decryption_failure.rb
176
+ - lib/chamber/errors/disallowed_class.rb
191
177
  - lib/chamber/errors/environment_conversion.rb
192
178
  - lib/chamber/errors/non_conforming_key.rb
193
179
  - lib/chamber/file.rb
@@ -210,7 +196,9 @@ files:
210
196
  - lib/chamber/keys/encryption.rb
211
197
  - lib/chamber/namespace_set.rb
212
198
  - lib/chamber/rails.rb
199
+ - lib/chamber/refinements/deep_dup.rb
213
200
  - lib/chamber/refinements/enumerable.rb
201
+ - lib/chamber/refinements/hash.rb
214
202
  - lib/chamber/rubinius_fix.rb
215
203
  - lib/chamber/settings.rb
216
204
  - lib/chamber/types/secured.rb
@@ -235,14 +223,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
235
223
  requirements:
236
224
  - - ">="
237
225
  - !ruby/object:Gem::Version
238
- version: 2.1.0
226
+ version: 2.7.5
239
227
  required_rubygems_version: !ruby/object:Gem::Requirement
240
228
  requirements:
241
- - - ">="
229
+ - - ">"
242
230
  - !ruby/object:Gem::Version
243
- version: '0'
231
+ version: 1.3.1
244
232
  requirements: []
245
- rubygems_version: 3.1.4
233
+ rubygems_version: 3.1.6
246
234
  signing_key:
247
235
  specification_version: 4
248
236
  summary: A surprisingly configurable convention-based approach to managing your application's
metadata.gz.sig CHANGED
Binary file
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Hash
4
- def transform_keys
5
- return enum_for(:transform_keys) { size } unless block_given?
6
-
7
- result = {}
8
-
9
- each_key do |key|
10
- result[yield(key)] = self[key]
11
- end
12
-
13
- result
14
- end
15
- end