chamber 2.4.0 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -930
  3. data/Rakefile +6 -0
  4. data/lib/chamber.rb +11 -7
  5. data/lib/chamber/binary/heroku.rb +45 -25
  6. data/lib/chamber/binary/runner.rb +82 -44
  7. data/lib/chamber/binary/travis.rb +14 -8
  8. data/lib/chamber/commands/base.rb +1 -2
  9. data/lib/chamber/commands/comparable.rb +0 -1
  10. data/lib/chamber/commands/compare.rb +1 -1
  11. data/lib/chamber/commands/files.rb +0 -1
  12. data/lib/chamber/commands/heroku.rb +2 -3
  13. data/lib/chamber/commands/heroku/push.rb +1 -1
  14. data/lib/chamber/commands/initialize.rb +69 -12
  15. data/lib/chamber/commands/securable.rb +9 -4
  16. data/lib/chamber/commands/secure.rb +1 -1
  17. data/lib/chamber/commands/show.rb +20 -4
  18. data/lib/chamber/commands/travis.rb +0 -1
  19. data/lib/chamber/configuration.rb +5 -5
  20. data/lib/chamber/context_resolver.rb +12 -12
  21. data/lib/chamber/decryption_key.rb +51 -0
  22. data/lib/chamber/environmentable.rb +4 -1
  23. data/lib/chamber/errors/decryption_failure.rb +6 -0
  24. data/lib/chamber/file.rb +7 -8
  25. data/lib/chamber/file_set.rb +23 -22
  26. data/lib/chamber/filters/boolean_conversion_filter.rb +1 -2
  27. data/lib/chamber/filters/decryption_filter.rb +42 -25
  28. data/lib/chamber/filters/encryption_filter.rb +7 -5
  29. data/lib/chamber/filters/environment_filter.rb +7 -7
  30. data/lib/chamber/filters/failed_decryption_filter.rb +41 -0
  31. data/lib/chamber/filters/namespace_filter.rb +1 -1
  32. data/lib/chamber/filters/secure_filter.rb +3 -5
  33. data/lib/chamber/filters/translate_secure_keys_filter.rb +5 -24
  34. data/lib/chamber/namespace_set.rb +6 -6
  35. data/lib/chamber/rails.rb +1 -3
  36. data/lib/chamber/rails/railtie.rb +6 -3
  37. data/lib/chamber/settings.rb +34 -32
  38. data/lib/chamber/version.rb +1 -1
  39. data/spec/fixtures/settings.yml +1 -0
  40. data/spec/lib/chamber/commands/files_spec.rb +4 -2
  41. data/spec/lib/chamber/commands/secure_spec.rb +8 -5
  42. data/spec/lib/chamber/commands/show_spec.rb +18 -3
  43. data/spec/lib/chamber/context_resolver_spec.rb +38 -18
  44. data/spec/lib/chamber/file_set_spec.rb +73 -52
  45. data/spec/lib/chamber/file_spec.rb +37 -23
  46. data/spec/lib/chamber/filters/boolean_conversion_filter_spec.rb +35 -33
  47. data/spec/lib/chamber/filters/decryption_filter_spec.rb +142 -21
  48. data/spec/lib/chamber/filters/encryption_filter_spec.rb +51 -19
  49. data/spec/lib/chamber/filters/environment_filter_spec.rb +12 -6
  50. data/spec/lib/chamber/filters/failed_decryption_filter_spec.rb +53 -0
  51. data/spec/lib/chamber/filters/insecure_filter_spec.rb +38 -18
  52. data/spec/lib/chamber/filters/namespace_filter_spec.rb +38 -38
  53. data/spec/lib/chamber/filters/secure_filter_spec.rb +10 -10
  54. data/spec/lib/chamber/filters/translate_secure_keys_filter_spec.rb +9 -6
  55. data/spec/lib/chamber/namespace_set_spec.rb +7 -5
  56. data/spec/lib/chamber/settings_spec.rb +168 -79
  57. data/spec/lib/chamber_spec.rb +72 -71
  58. metadata +22 -21
  59. data/lib/chamber/errors/undecryptable_value_error.rb +0 -6
  60. data/templates/settings.yml +0 -14
@@ -5,26 +5,26 @@ module Chamber
5
5
  module Filters
6
6
  describe InsecureFilter do
7
7
  it 'will return values which are marked as "secure" if they are unencrypted' do
8
- filtered_settings = InsecureFilter.execute( data: {
9
- _secure_my_secure_setting: 'hello' })
8
+ filtered_settings = InsecureFilter.execute(data: {
9
+ _secure_my_secure_setting: 'hello' })
10
10
 
11
11
  expect(filtered_settings._secure_my_secure_setting).to match 'hello'
12
12
  end
13
13
 
14
14
  it 'will not return values which are not marked as "secure"' do
15
- filtered_settings = InsecureFilter.execute( data: {
16
- my_secure_setting: 'hello' })
15
+ filtered_settings = InsecureFilter.execute(data: {
16
+ my_secure_setting: 'hello' })
17
17
 
18
18
  expect(filtered_settings.my_secure_setting).to be_nil
19
19
  end
20
20
 
21
21
  it 'will properly return values even if they are mixed and deeply nested' do
22
- filtered_settings = InsecureFilter.execute( data: {
23
- _secure_setting: 'hello',
24
- secure_setting: 'goodbye',
25
- secure_group: {
26
- _secure_nested_setting: 'movie',
27
- insecure_nested_setting: 'dinner' }})
22
+ filtered_settings = InsecureFilter.execute(data: {
23
+ _secure_setting: 'hello',
24
+ secure_setting: 'goodbye',
25
+ secure_group: {
26
+ _secure_nested_setting: 'movie',
27
+ insecure_nested_setting: 'dinner' } })
28
28
 
29
29
  expect(filtered_settings._secure_setting).to eql 'hello'
30
30
  expect(filtered_settings.secure_setting).to be_nil
@@ -33,14 +33,34 @@ describe InsecureFilter do
33
33
  end
34
34
 
35
35
  it 'will not return values which are encrypted' do
36
- filtered_settings = InsecureFilter.execute( data: {
37
- _secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
38
- secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
39
- _secure_other_setting: 'hello',
40
- secure_group: {
41
- _secure_nested_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
42
- _secure_other_nested_setting: 'goodbye',
43
- insecure_nested_setting: 'dinner' }})
36
+ filtered_settings = InsecureFilter.execute(
37
+ data: {
38
+ _secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpss' \
39
+ 'pg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzC' \
40
+ 'MJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YG' \
41
+ 'DJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6ag' \
42
+ 'y1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMn' \
43
+ 'gJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfN' \
44
+ 'xMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
45
+ secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpss' \
46
+ 'pg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzC' \
47
+ 'MJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YG' \
48
+ 'DJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6ag' \
49
+ 'y1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMn' \
50
+ 'gJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfN' \
51
+ 'xMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
52
+ _secure_other_setting: 'hello',
53
+ secure_group: {
54
+ _secure_nested_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTh' \
55
+ 'aV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4' \
56
+ 'akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGy' \
57
+ 'dkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9' \
58
+ 'ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8' \
59
+ 'QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZ' \
60
+ 'gfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMn' \
61
+ 'z84XzmUp2Y0H1jPgGkBKQJKArfQ==',
62
+ _secure_other_nested_setting: 'goodbye',
63
+ insecure_nested_setting: 'dinner' } })
44
64
 
45
65
  expect(filtered_settings._secure_setting?).to eql false
46
66
  expect(filtered_settings.secure_setting?).to eql false
@@ -6,67 +6,67 @@ module Chamber
6
6
  module Filters
7
7
  describe NamespaceFilter do
8
8
  it 'can filter settings data based on the settings namespaces' do
9
- filtered_settings = NamespaceFilter.execute(data: {
10
- namespace_value: {
11
- namespace_setting: 'value 1' },
12
- other_namespace_value: {
13
- other_namespace_setting: 'value 2' }},
14
- namespaces: [
15
- 'namespace_value',
16
- 'other_namespace_value' ])
9
+ filtered_settings = NamespaceFilter.execute(
10
+ data: {
11
+ namespace_value: {
12
+ namespace_setting: 'value 1' },
13
+ other_namespace_value: {
14
+ other_namespace_setting: 'value 2' } },
15
+ namespaces: %w{namespace_value other_namespace_value})
17
16
 
18
17
  expect(filtered_settings.namespace_setting).to eql 'value 1'
19
18
  expect(filtered_settings.other_namespace_setting).to eql 'value 2'
20
19
  end
21
20
 
22
21
  it 'ignores data which is not part of a namespace' do
23
- filtered_settings = NamespaceFilter.execute(data: {
24
- namespace_value: {
25
- namespace_setting: 'value 1' },
26
- non_namespaced_value: {
27
- non_namespaced_setting: 'value 2' }},
28
- namespaces: [
29
- 'namespace_value' ])
22
+ filtered_settings = NamespaceFilter.execute(
23
+ data: {
24
+ namespace_value: {
25
+ namespace_setting: 'value 1' },
26
+ non_namespaced_value: {
27
+ non_namespaced_setting: 'value 2' } },
28
+ namespaces: [
29
+ 'namespace_value'])
30
30
 
31
31
  expect(filtered_settings.namespace_setting).to eql 'value 1'
32
32
  expect(filtered_settings.non_namespaced_setting).to be_nil
33
33
  end
34
34
 
35
35
  it 'ignores namespaces which do not exist in the data' do
36
- filtered_settings = NamespaceFilter.execute(data: {
37
- namespace_value: {
38
- namespace_setting: 'value 1' }},
39
- namespaces: [
40
- 'namespace_value',
41
- 'other_namespace_value' ])
36
+ filtered_settings = NamespaceFilter.execute(
37
+ data: {
38
+ namespace_value: {
39
+ namespace_setting: 'value 1' } },
40
+ namespaces: %w{namespace_value other_namespace_value})
42
41
 
43
42
  expect(filtered_settings.namespace_setting).to eql 'value 1'
44
43
  end
45
44
 
46
45
  it 'does not filter data if it does not include any namespaces' do
47
- filtered_settings = NamespaceFilter.execute(data: {
48
- non_namespaced_setting: 'value 1' },
49
- namespaces: [])
46
+ filtered_settings = NamespaceFilter.execute(
47
+ data: {
48
+ non_namespaced_setting: 'value 1' },
49
+ namespaces: [])
50
50
 
51
51
  expect(filtered_settings.non_namespaced_setting).to eql 'value 1'
52
52
  end
53
53
 
54
54
  it 'can filter if it is given NamespaceSets' do
55
- filtered_settings = NamespaceFilter.execute(data: {
56
- namespace_value: {
57
- namespace_setting: 'value 1',
58
- another_namespace_setting: 'value 2' },
59
- other_namespace_value: {
60
- namespace_setting_1: 'value 1',
61
- another_namespace_setting_2: 'value 2' },
62
- non_namespaced_value: 'value 3' },
63
- namespaces:
64
- NamespaceSet.new(['namespace_value', 'other_namespace_value']) )
55
+ filtered_settings = NamespaceFilter.execute(
56
+ data: {
57
+ namespace_value: {
58
+ namespace_setting: 'value 1',
59
+ another_namespace_setting: 'value 2' },
60
+ other_namespace_value: {
61
+ namespace_setting_1: 'value 1',
62
+ another_namespace_setting_2: 'value 2' },
63
+ non_namespaced_value: 'value 3' },
64
+ namespaces: NamespaceSet.new(%w{namespace_value other_namespace_value}))
65
65
 
66
- expect(filtered_settings.to_hash).to eql( 'namespace_setting' => 'value 1',
67
- 'another_namespace_setting' => 'value 2',
68
- 'namespace_setting_1' => 'value 1',
69
- 'another_namespace_setting_2' => 'value 2')
66
+ expect(filtered_settings.to_hash).to eql('namespace_setting' => 'value 1',
67
+ 'another_namespace_setting' => 'value 2',
68
+ 'namespace_setting_1' => 'value 1',
69
+ 'another_namespace_setting_2' => 'value 2')
70
70
  end
71
71
  end
72
72
  end
@@ -5,26 +5,26 @@ module Chamber
5
5
  module Filters
6
6
  describe SecureFilter do
7
7
  it 'will return values which are marked as "secure"' do
8
- filtered_settings = SecureFilter.execute( data: {
9
- _secure_my_secure_setting: 'hello' })
8
+ filtered_settings = SecureFilter.execute(data: {
9
+ _secure_my_secure_setting: 'hello' })
10
10
 
11
11
  expect(filtered_settings._secure_my_secure_setting).to match 'hello'
12
12
  end
13
13
 
14
14
  it 'will not return values which are not marked as "secure"' do
15
- filtered_settings = SecureFilter.execute( data: {
16
- my_secure_setting: 'hello' })
15
+ filtered_settings = SecureFilter.execute(data: {
16
+ my_secure_setting: 'hello' })
17
17
 
18
18
  expect(filtered_settings.my_secure_setting).to be_nil
19
19
  end
20
20
 
21
21
  it 'will properly return values even if they are mixed and deeply nested' do
22
- filtered_settings = SecureFilter.execute( data: {
23
- _secure_setting: 'hello',
24
- secure_setting: 'goodbye',
25
- secure_group: {
26
- _secure_nested_setting: 'movie',
27
- insecure_nested_setting: 'dinner' }})
22
+ filtered_settings = SecureFilter.execute(data: {
23
+ _secure_setting: 'hello',
24
+ secure_setting: 'goodbye',
25
+ secure_group: {
26
+ _secure_nested_setting: 'movie',
27
+ insecure_nested_setting: 'dinner' } })
28
28
 
29
29
  expect(filtered_settings._secure_setting).to eql 'hello'
30
30
  expect(filtered_settings.secure_setting).to be_nil
@@ -5,22 +5,25 @@ module Chamber
5
5
  module Filters
6
6
  describe TranslateSecureKeysFilter do
7
7
  it 'will translate keys if they start with "_secure_"' do
8
- filtered_settings = TranslateSecureKeysFilter.execute( data: {
9
- _secure_my_secure_setting: 'hello' })
8
+ filtered_settings = TranslateSecureKeysFilter.execute(
9
+ data: {
10
+ _secure_my_secure_setting: 'hello' })
10
11
 
11
12
  expect(filtered_settings.my_secure_setting).to eql 'hello'
12
13
  end
13
14
 
14
15
  it 'will not translate keys if they do not start with "_secure_"' do
15
- filtered_settings = TranslateSecureKeysFilter.execute( data: {
16
- my_secure_setting: 'hello' })
16
+ filtered_settings = TranslateSecureKeysFilter.execute(
17
+ data: {
18
+ my_secure_setting: 'hello' })
17
19
 
18
20
  expect(filtered_settings.my_secure_setting).to eql 'hello'
19
21
  end
20
22
 
21
23
  it 'will not translate the key if it starts with "secure"' do
22
- filtered_settings = TranslateSecureKeysFilter.execute( data: {
23
- secure_setting: 'hello' })
24
+ filtered_settings = TranslateSecureKeysFilter.execute(
25
+ data: {
26
+ secure_setting: 'hello' })
24
27
 
25
28
  expect(filtered_settings.secure_setting).to eql 'hello'
26
29
  end
@@ -4,8 +4,8 @@ require 'chamber/namespace_set'
4
4
  module Chamber
5
5
  describe NamespaceSet do
6
6
  it 'can create a set from from a hash' do
7
- namespace_set = NamespaceSet.new( environment: :development,
8
- hostname: 'my host')
7
+ namespace_set = NamespaceSet.new(environment: :development,
8
+ hostname: 'my host')
9
9
 
10
10
  expect(namespace_set).to eq ['development', 'my host']
11
11
  end
@@ -50,7 +50,9 @@ describe NamespaceSet do
50
50
  expect(namespace_set.object_id).not_to eq original_set.object_id
51
51
  end
52
52
 
53
- it 'when creating itself from another NamespaceSet, it does not nest the NamespaceSets' do
53
+ it 'when creating itself from another NamespaceSet, it does not nest the ' \
54
+ 'NamespaceSets' do
55
+
54
56
  original_set = NamespaceSet[:development, 'my host']
55
57
  namespace_set = NamespaceSet.new(original_set)
56
58
 
@@ -105,11 +107,11 @@ describe NamespaceSet do
105
107
  end
106
108
 
107
109
  it 'will process a value by executing it if it is a callable' do
108
- namespace_set = NamespaceSet[ -> { 'callable' } ]
110
+ namespace_set = NamespaceSet[-> { 'callable' }]
109
111
 
110
112
  expect(namespace_set).to eq ['callable']
111
113
 
112
- namespace_set = NamespaceSet.new( :my_namespace => -> { 'callable' } )
114
+ namespace_set = NamespaceSet.new(my_namespace: -> { 'callable' })
113
115
 
114
116
  expect(namespace_set).to eq ['callable']
115
117
  end
@@ -4,28 +4,28 @@ require 'chamber/settings'
4
4
  module Chamber
5
5
  describe Settings do
6
6
  it 'can verify that it is equal to another Settings object' do
7
- settings = Settings.new( settings: {setting: 'value'},
8
- namespaces: ['good'])
9
- other_settings = Settings.new( settings: {setting: 'value'},
10
- namespaces: ['good'])
7
+ settings = Settings.new(settings: { setting: 'value' },
8
+ namespaces: ['good'])
9
+ other_settings = Settings.new(settings: { setting: 'value' },
10
+ namespaces: ['good'])
11
11
 
12
12
  expect(settings).to eql other_settings
13
13
  end
14
14
 
15
15
  it 'does not consider itself equal if the namespaces are not equal' do
16
- settings = Settings.new( settings: {setting: 'value'},
17
- namespaces: ['good'])
18
- other_settings = Settings.new( settings: {setting: 'value'},
19
- namespaces: ['bad'])
16
+ settings = Settings.new(settings: { setting: 'value' },
17
+ namespaces: ['good'])
18
+ other_settings = Settings.new(settings: { setting: 'value' },
19
+ namespaces: ['bad'])
20
20
 
21
21
  expect(settings).not_to eql other_settings
22
22
  end
23
23
 
24
24
  it 'does not consider itself equal if the settings are not equal' do
25
- settings = Settings.new( settings: {setting: 'value'},
26
- namespaces: ['good'])
27
- other_settings = Settings.new( settings: {setting: 'value 1'},
28
- namespaces: ['good'])
25
+ settings = Settings.new(settings: { setting: 'value' },
26
+ namespaces: ['good'])
27
+ other_settings = Settings.new(settings: { setting: 'value 1' },
28
+ namespaces: ['good'])
29
29
 
30
30
  expect(settings).not_to eql other_settings
31
31
  end
@@ -34,11 +34,11 @@ describe Settings do
34
34
  settings = Settings.new(settings: {
35
35
  my_setting: 'value',
36
36
  level_1: {
37
- level_2: {
37
+ level_2: {
38
38
  some_setting: 'hello',
39
39
  another: 'goodbye',
40
40
  },
41
- body: 'gracias',
41
+ body: 'gracias',
42
42
  },
43
43
  there: 'was not that easy?',
44
44
  })
@@ -52,45 +52,53 @@ describe Settings do
52
52
  )
53
53
  end
54
54
 
55
- it 'sorts environment variables by name when converted to an environment hash so that they are easier to parse for humans' do
55
+ it 'sorts environment variables by name when converted to an environment hash so ' \
56
+ 'that they are easier to parse for humans' do
57
+
56
58
  settings = Settings.new(settings: { 'C' => 'value',
57
59
  'D' => 'value',
58
60
  'A' => 'value',
59
61
  'E' => 'value',
60
62
  'B' => 'value' })
61
63
 
62
- expect(settings.to_environment.to_a).to eql([['A', 'value'],
63
- ['B', 'value'],
64
- ['C', 'value'],
65
- ['D', 'value'],
66
- ['E', 'value']])
64
+ expect(settings.to_environment.to_a).to eql([%w{A value},
65
+ %w{B value},
66
+ %w{C value},
67
+ %w{D value},
68
+ %w{E value}])
67
69
  end
68
70
 
69
71
  it 'can convert itself into a string' do
70
72
  settings = Settings.new(settings: {
71
73
  my_setting: 'value',
72
74
  level_1: {
73
- level_2: {
75
+ level_2: {
74
76
  some_setting: 'hello',
75
77
  another: 'goodbye',
76
78
  },
77
- body: 'gracias',
79
+ body: 'gracias',
78
80
  },
79
81
  there: 'was not that easy?',
80
82
  })
81
83
 
82
- expect(settings.to_s).to eql %Q{LEVEL_1_BODY="gracias" LEVEL_1_LEVEL_2_ANOTHER="goodbye" LEVEL_1_LEVEL_2_SOME_SETTING="hello" MY_SETTING="value" THERE="was not that easy?"}
84
+ expect(settings.to_s).to eql %w{
85
+ LEVEL_1_BODY="gracias"
86
+ LEVEL_1_LEVEL_2_ANOTHER="goodbye"
87
+ LEVEL_1_LEVEL_2_SOME_SETTING="hello"
88
+ MY_SETTING="value"
89
+ THERE="was not that easy?"
90
+ }.join(' ')
83
91
  end
84
92
 
85
93
  it 'can convert itself into a string with custom options' do
86
94
  settings = Settings.new(settings: {
87
95
  my_setting: 'value',
88
96
  level_1: {
89
- level_2: {
97
+ level_2: {
90
98
  some_setting: 'hello',
91
99
  another: 'goodbye',
92
100
  },
93
- body: 'gracias',
101
+ body: 'gracias',
94
102
  },
95
103
  there: 'was not that easy?',
96
104
  })
@@ -110,32 +118,32 @@ HEREDOC
110
118
  end
111
119
 
112
120
  it 'can merge itself with a hash' do
113
- settings = Settings.new(settings: {setting: 'value'})
121
+ settings = Settings.new(settings: { setting: 'value' })
114
122
  other_settings = { other_setting: 'another value' }
115
123
 
116
124
  merged_settings = settings.merge(other_settings)
117
125
 
118
126
  expect(merged_settings).to eq('setting' => 'value',
119
- 'other_setting' => 'another value')
127
+ 'other_setting' => 'another value')
120
128
  end
121
129
 
122
130
  it 'can merge itself with Settings' do
123
- settings = Settings.new(settings: {setting: 'value'},
131
+ settings = Settings.new(settings: { setting: 'value' },
124
132
  namespaces: ['good'])
125
- other_settings = Settings.new(settings: {other_setting: 'another value'},
133
+ other_settings = Settings.new(settings: { other_setting: 'another value' },
126
134
  namespaces: ['bad'])
127
135
 
128
136
  merged_settings = settings.merge(other_settings)
129
137
 
130
138
  expect(merged_settings).to eql Settings.new(settings: {
131
- setting: 'value',
132
- other_setting: 'another value' },
133
- namespaces: ['good', 'bad'])
139
+ setting: 'value',
140
+ other_setting: 'another value' },
141
+ namespaces: %w{good bad})
134
142
  end
135
143
 
136
144
  it 'does not manipulate the existing Settings but instead returns a new one' do
137
- settings = Settings.new(settings: {setting: 'value'})
138
- other_settings = Settings.new(settings: {other_setting: 'another value'})
145
+ settings = Settings.new(settings: { setting: 'value' })
146
+ other_settings = Settings.new(settings: { other_setting: 'another value' })
139
147
 
140
148
  merged_settings = settings.merge(other_settings)
141
149
 
@@ -144,7 +152,7 @@ HEREDOC
144
152
  end
145
153
 
146
154
  it 'can convert itself into a hash' do
147
- settings = Settings.new(settings: {setting: 'value'})
155
+ settings = Settings.new(settings: { setting: 'value' })
148
156
 
149
157
  expect(settings.to_hash).to eql('setting' => 'value')
150
158
  expect(settings.to_hash).to be_a Hash
@@ -155,28 +163,30 @@ HEREDOC
155
163
  settings = Settings.new(settings: {
156
164
  my_setting: 'value',
157
165
  level_1: {
158
- level_2: {
166
+ level_2: {
159
167
  some_setting: 'hello',
160
168
  another: 'goodbye',
161
169
  },
162
- body: 'gracias',
170
+ body: 'gracias',
163
171
  },
164
172
  there: 'was not that easy?',
165
173
  })
166
174
 
167
175
  expect(settings.to_flattened_name_hash).to eql(
168
- ['my_setting'] => 'value',
169
- ['level_1', 'level_2', 'some_setting'] => 'hello',
170
- ['level_1', 'level_2', 'another'] => 'goodbye',
171
- ['level_1', 'body'] => 'gracias',
172
- ['there'] => 'was not that easy?',
176
+ %w{my_setting} => 'value',
177
+ %w{level_1 level_2 some_setting} => 'hello',
178
+ %w{level_1 level_2 another} => 'goodbye',
179
+ %w{level_1 body} => 'gracias',
180
+ %w{there} => 'was not that easy?',
173
181
  )
174
182
  expect(settings.to_flattened_name_hash).to be_a Hash
175
183
  expect(settings.to_flattened_name_hash).not_to be_a Hashie::Mash
176
184
  end
177
185
 
178
- it 'does not allow manipulation of the internal setting hash when converted to a Hash' do
179
- settings = Settings.new(settings: {setting: 'value'})
186
+ it 'does not allow manipulation of the internal setting hash when converted to ' \
187
+ 'a Hash' do
188
+
189
+ settings = Settings.new(settings: { setting: 'value' })
180
190
 
181
191
  settings_hash = settings.to_hash
182
192
  settings_hash['setting'] = 'foo'
@@ -186,60 +196,69 @@ HEREDOC
186
196
  end
187
197
 
188
198
  it 'allows messages to be passed through to the underlying data' do
189
- settings = Settings.new(settings: {setting: 'value'})
199
+ settings = Settings.new(settings: { setting: 'value' })
190
200
 
191
201
  expect(settings.setting).to eql 'value'
192
202
  end
193
203
 
194
204
  it 'will still raise an error if the underlying data does not respond to it' do
195
- settings = Settings.new(settings: {setting: 'value'})
205
+ settings = Settings.new(settings: { setting: 'value' })
196
206
 
197
207
  expect { settings.unknown }.to raise_error NoMethodError
198
208
  end
199
209
 
200
210
  it 'can notify properly whether it responds to messages if the underlying data does' do
201
- settings = Settings.new(settings: {setting: 'value'})
211
+ settings = Settings.new(settings: { setting: 'value' })
202
212
 
203
213
  expect(settings.respond_to?(:setting)).to be_a TrueClass
204
214
  end
205
215
 
206
216
  it 'only includes namespaced data if any exists' do
207
217
  settings = Settings.new(settings: {
208
- namespace_value: {
209
- namespace_setting: 'value' },
210
- other_namespace_value: {
211
- other_namespace_setting: 'value' },
212
- non_namespace_setting: 'other value'
218
+ namespace_value: {
219
+ namespace_setting: 'value' },
220
+ other_namespace_value: {
221
+ other_namespace_setting: 'value' },
222
+ non_namespace_setting: 'other value',
213
223
  },
214
- namespaces: ['namespace_value', 'other_namespace_value'])
224
+ namespaces: %w{namespace_value other_namespace_value})
215
225
 
216
- expect(settings).to eq('namespace_setting' => 'value',
217
- 'other_namespace_setting' => 'value')
226
+ expect(settings).to eq('namespace_setting' => 'value',
227
+ 'other_namespace_setting' => 'value')
218
228
  end
219
229
 
220
230
  it 'can decrypt a setting if it finds a secure key' do
221
- settings = Settings.new(settings: {
222
- _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
223
- },
224
- decryption_key: './spec/spec_key')
231
+ settings = Settings.new(
232
+ settings: {
233
+ _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
234
+ 'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
235
+ 'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
236
+ 'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
237
+ 'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
238
+ '1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
239
+ 'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
240
+ 'p2Y0H1jPgGkBKQJKArfQ==',
241
+ },
242
+ decryption_key: './spec/spec_key')
225
243
 
226
244
  expect(settings).to eq('my_encrypted_setting' => 'hello')
227
245
  end
228
246
 
229
247
  it 'can encrypt a setting if it finds a secure key' do
230
- settings = Settings.new(settings: {
231
- _secure_my_encrypted_setting: 'hello'
248
+ settings = Settings.new(settings: {
249
+ _secure_my_encrypted_setting: 'hello',
232
250
  },
233
251
  encryption_key: './spec/spec_key.pub',
234
252
  pre_filters: [],
235
- post_filters: [ Filters::EncryptionFilter ])
253
+ post_filters: [Filters::EncryptionFilter])
236
254
 
237
- expect(settings._secure_my_encrypted_setting).to match Filters::EncryptionFilter::BASE64_STRING_PATTERN
255
+ expect(settings._secure_my_encrypted_setting).to match \
256
+ Filters::EncryptionFilter::BASE64_STRING_PATTERN
238
257
  end
239
258
 
240
259
  it 'can encrypt a settings without explicitly having to have a filter passed' do
241
- settings = Settings.new(settings: {
242
- _secure_my_encrypted_setting: 'hello'
260
+ settings = Settings.new(settings: {
261
+ _secure_my_encrypted_setting: 'hello',
243
262
  },
244
263
  decryption_key: './spec/spec_key',
245
264
  encryption_key: './spec/spec_key.pub')
@@ -248,22 +267,31 @@ HEREDOC
248
267
 
249
268
  secure_settings = settings.secure
250
269
 
251
- expect(secure_settings.my_encrypted_setting).to match Filters::EncryptionFilter::BASE64_STRING_PATTERN
270
+ expect(secure_settings.my_encrypted_setting).to match \
271
+ Filters::EncryptionFilter::BASE64_STRING_PATTERN
252
272
  end
253
273
 
254
274
  it 'can check if it is equal to other items which can be converted into hashes' do
255
- settings = Settings.new(settings: {setting: 'value'})
275
+ settings = Settings.new(settings: { setting: 'value' })
256
276
 
257
277
  expect(settings).to eq('setting' => 'value')
258
278
  end
259
279
 
260
280
  it 'can filter securable settings' do
261
- settings = Settings.new(settings: {
262
- _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
263
- _secure_my_unencrypted_setting: 'nifty',
264
- my_insecure_setting: 'goodbye',
265
- },
266
- decryption_key: './spec/spec_key')
281
+ settings = Settings.new(
282
+ settings: {
283
+ _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
284
+ 'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
285
+ 'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
286
+ 'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
287
+ 'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
288
+ '1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
289
+ 'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
290
+ 'p2Y0H1jPgGkBKQJKArfQ==',
291
+ _secure_my_unencrypted_setting: 'nifty',
292
+ my_insecure_setting: 'goodbye',
293
+ },
294
+ decryption_key: './spec/spec_key')
267
295
 
268
296
  secured_settings = settings.securable
269
297
 
@@ -273,12 +301,20 @@ HEREDOC
273
301
  end
274
302
 
275
303
  it 'can filter unencrypted settings' do
276
- settings = Settings.new(settings: {
277
- _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
278
- _secure_my_unencrypted_setting: 'nifty',
279
- my_insecure_setting: 'goodbye',
280
- },
281
- decryption_key: './spec/spec_key')
304
+ settings = Settings.new(
305
+ settings: {
306
+ _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
307
+ 'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
308
+ 'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
309
+ 'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
310
+ 'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
311
+ '1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
312
+ 'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
313
+ 'p2Y0H1jPgGkBKQJKArfQ==',
314
+ _secure_my_unencrypted_setting: 'nifty',
315
+ my_insecure_setting: 'goodbye',
316
+ },
317
+ decryption_key: './spec/spec_key')
282
318
 
283
319
  secured_settings = settings.insecure
284
320
 
@@ -286,5 +322,58 @@ HEREDOC
286
322
  expect(secured_settings.my_unencrypted_setting).to eql 'nifty'
287
323
  expect(secured_settings.my_insecure_setting?).to eql false
288
324
  end
325
+
326
+ it 'raises an exception when it accesses a value which cannot be decrypted' do
327
+ settings = Settings.new(
328
+ settings: {
329
+ _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
330
+ 'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
331
+ 'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
332
+ 'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
333
+ 'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
334
+ '1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
335
+ 'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
336
+ 'p2Y0H1jPgGkBKQJKArfQ==',
337
+ },
338
+ )
339
+
340
+ expect { settings.my_encrypted_setting }.
341
+ to raise_error Chamber::Errors::DecryptionFailure
342
+ end
343
+
344
+ it 'prefers environment variable values over encrypted values' do
345
+ ENV['MY_ENCRYPTED_SETTING'] = 'my env setting'
346
+ ENV['ENCRYPTED_GROUP_MY_ENCRYPTED_GROUP_SETTING'] = 'my env group'
347
+
348
+ settings = Settings.new(
349
+ settings: {
350
+ _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
351
+ 'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
352
+ 'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
353
+ 'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
354
+ 'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
355
+ '1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
356
+ 'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
357
+ 'p2Y0H1jPgGkBKQJKArfQ==',
358
+ encrypted_group: {
359
+ _secure_my_encrypted_group_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdn' \
360
+ 'MoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3Fx' \
361
+ 'ptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEA' \
362
+ 'QLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUT' \
363
+ 'f34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5k' \
364
+ 'LAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlz' \
365
+ 'pKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgU' \
366
+ 'Kc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84Xz' \
367
+ 'mUp2Y0H1jPgGkBKQJKArfQ==',
368
+ },
369
+ },
370
+ )
371
+
372
+ expect(settings.my_encrypted_setting).to eql 'my env setting'
373
+ expect(settings.encrypted_group.my_encrypted_group_setting).to eql 'my env group'
374
+
375
+ ENV['MY_ENCRYPTED_SETTING'] = nil
376
+ ENV['ENCRYPTED_GROUP_MY_ENCRYPTED_GROUP_SETTING'] = nil
377
+ end
289
378
  end
290
379
  end