nuclear_secrets 1.0.1 → 1.0.2

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
  SHA1:
3
- metadata.gz: 57e88636b13f8f0b1e9697a6dc9621f9a3d2a8ba
4
- data.tar.gz: 823b10f98e3078d78fea563e33455ea03ce188b6
3
+ metadata.gz: 175b07894161bdae17411c570da95b2378fb64a8
4
+ data.tar.gz: ed3c759584c3e898ecf93461df2a6705c1d76368
5
5
  SHA512:
6
- metadata.gz: c48b0e1421e051ab3d687acf119ae42e315ee7b9cc83034a6c189a797dca4e94cc6aba3aafa75aedf3631b6194f11154b3f8ffd6f496dd9162b5479e36c097e8
7
- data.tar.gz: 725ad3b2597c8b97e2e3fe0ad231afc8c47a801ef89abe59938e3f25abd4c7e3c9e20d82adc2cb13f3729261440aa18aef0eadbcb10bcb1e6e17bfdc206bfec7
6
+ metadata.gz: 9e57fb6daf72613508d0008fe2a20a3a5f2109856b61a840fa764d5f62c10fb15d2274d153b52d94e90aaf54bff78b3b18e0df1e1a1a42b201ff705155c140ab
7
+ data.tar.gz: 1c71339468af3cc4f234991b9e6a7d4fdf5fa863c67eadb99ae9fc419413c64e784684aefb5e5ed2aaf8c327d4b1e9c87b50501c610cac72948148f7da4b6f4b
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # NuclearSecrets
1
+ # Nuclear Secrets
2
2
  Quell rails secret espionage by verifying what secrets exist and their types in your rails application
3
3
 
4
4
  ## Usage
@@ -30,6 +30,21 @@ end
30
30
  ```
31
31
  Include all secrets that your application utilizes, and their types, in `required_secrets` hash
32
32
 
33
+ ## Advanced Usage
34
+ In addition to being able to supply NuclearSecrets with the type of a secret,
35
+ you can also pass a Proc or a Lambda. If the proc or lamba returns true when
36
+ passed the value of the secret, then the secret will be allowed.
37
+
38
+ ```
39
+ NuclearSecrets.configure do |config|
40
+ config.required_secrets = {
41
+ my_string_secret: String,
42
+ my_numeric_secret: Fixnum,
43
+ my_secret: Proc.new { |secret| secret.is_worthy? }
44
+ }
45
+ end
46
+ ```
47
+
33
48
  ## Contributing
34
49
  Contribution directions go here.
35
50
 
@@ -1,61 +1,78 @@
1
1
  require "nuclear_secrets/engine"
2
+ require "nuclear_secrets/errors"
2
3
 
3
4
  module NuclearSecrets
4
- class NuclearSecretError < StandardError
5
- def initialize(secrets: [])
6
- @secrets = secrets
7
- end
8
-
9
- def get_error_list
10
- @secrets.reduce("") do |message, current|
11
- message << "#{current.first} of type #{current.last} \n"
12
- end
13
- end
14
- end
5
+ class << self
6
+ attr_accessor(:required_secrets)
15
7
 
16
- class RequiredSecretsListMissing < NuclearSecretError
17
- def message
18
- "You must include a required_secrets key in your config/secrets.yml file"
8
+ def configure
9
+ yield self if block_given?
19
10
  end
20
- end
21
11
 
22
- class SecretsMissingError < NuclearSecretError
23
- def initialize(secrets)
24
- super(secrets: secrets)
12
+ def make_type_check(type)
13
+ Proc.new { |item| item.class == type }
25
14
  end
26
15
 
27
- def message
28
- "Missing secrets: \n#{get_error_list}"
16
+ # secrets: hash of given secrets
17
+ # required_values: hash of required secrets
18
+ # key: key to build tuple for
19
+ # returns [key, required_type, given_type]
20
+ def build_secret_tuple(secrets, required_values, key)
21
+ [key, required_values[key], secrets[key]]
29
22
  end
30
- end
31
23
 
32
- class ExtraSecretsError < NuclearSecretError
33
- def initialize(secrets)
34
- super(secrets: secrets)
24
+ def build_pairs(keys, secrets)
25
+ keys.map do |k|
26
+ build_secret_tuple(secrets, required_secrets, k)
27
+ end
35
28
  end
36
29
 
37
- def message
38
- "Secrets not included in required_secrets list: \n#{get_error_list}"
30
+ def build_assertions(secrets, existing_keys)
31
+ existing_keys.map do |key|
32
+ if required_secrets[key].class == Class
33
+ make_type_check(required_secrets[key])
34
+ elsif required_secrets[key].respond_to? :call
35
+ required_secrets[key]
36
+ else
37
+ raise NuclearSecrets::InvalidRequiredSecretValue.new(
38
+ [
39
+ build_secret_tuple(secrets, required_secrets, key),
40
+ ],
41
+ )
42
+ end
43
+ end
39
44
  end
40
- end
41
-
42
- class << self
43
- attr_accessor(:required_secrets)
44
45
 
45
- def configure
46
- yield self if block_given?
46
+ def check_assertions(secrets, assertions)
47
+ secrets.to_a.zip(assertions).select do |pair|
48
+ result = pair.last.call(pair.first[1])
49
+ if !result
50
+ pair.first[0]
51
+ else
52
+ false
53
+ end
54
+ end.map do |pair|
55
+ flat_pair = pair.flatten
56
+ build_secret_tuple(secrets, required_secrets, flat_pair.first)
57
+ end
47
58
  end
48
59
 
49
60
  def check_secrets(secrets)
50
61
  raise NuclearSecrets::RequiredSecretsListMissing if required_secrets.nil?
51
- req_secret_pairs = required_secrets.map { |pair| [pair.first.to_sym, pair.last.to_s] }
52
- types = secrets.map { |pair| [pair.first, pair.last.class.to_s] }
62
+ req_keys = required_secrets.keys
63
+ existing_keys = secrets.keys
64
+
65
+ missing_keys = req_keys - existing_keys
66
+ extra_keys = existing_keys - req_keys
53
67
 
54
- missing_secrets = req_secret_pairs - types
55
- extra_secrets = types - req_secret_pairs
68
+ missing_pairs = build_pairs(missing_keys, secrets)
69
+ extra_pairs = build_pairs(extra_keys, secrets)
70
+ raise SecretsMissingError.new(missing_pairs) unless missing_keys.empty?
71
+ raise ExtraSecretsError.new(extra_pairs) unless extra_keys.empty?
56
72
 
57
- raise SecretsMissingError.new(missing_secrets) unless missing_secrets.empty?
58
- raise ExtraSecretsError.new(extra_secrets) unless extra_secrets.empty?
73
+ assertions = build_assertions(secrets, existing_keys)
74
+ error_pairs = check_assertions(secrets, assertions)
75
+ raise MismatchedSecretType.new(error_pairs) if !error_pairs.empty?
59
76
  end
60
77
  end
61
78
  end
@@ -0,0 +1,84 @@
1
+ module NuclearSecrets
2
+ class NuclearSecretError < StandardError
3
+ def initialize(secrets: [])
4
+ @secrets = secrets
5
+ end
6
+
7
+ def required_type_message(req_type)
8
+ if req_type.nil?
9
+ " of value nil"
10
+ elsif req_type.class == Class
11
+ " of type #{req_type}"
12
+ elsif req_type.class == Proc
13
+ source_pair = req_type.source_location
14
+ " of type Proc (defined in file: #{source_pair.first}, line: #{source_pair.last})"
15
+ else
16
+ " of value #{req_type}"
17
+ end
18
+ end
19
+
20
+ def given_type_message(given_type)
21
+ if given_type.nil?
22
+ "\n"
23
+ elsif given_type.class == String
24
+ " was given \"#{given_type}\"\n"
25
+ else
26
+ " was given #{given_type}\n"
27
+ end
28
+ end
29
+
30
+ def get_error_list
31
+ @secrets.reduce("") do |message, current|
32
+ message << current.first.to_s
33
+ message << required_type_message(current[1])
34
+ message << given_type_message(current.last)
35
+ end
36
+ end
37
+ end
38
+
39
+ class RequiredSecretsListMissing < NuclearSecretError
40
+ def message
41
+ "You must include a NuclearSecrets initializer in your app"
42
+ end
43
+ end
44
+
45
+ class SecretsMissingError < NuclearSecretError
46
+ def initialize(secrets)
47
+ super(secrets: secrets)
48
+ end
49
+
50
+ def message
51
+ "You are not using a secret that is required in the secrets list: \n#{get_error_list}"
52
+ end
53
+ end
54
+
55
+ class ExtraSecretsError < NuclearSecretError
56
+ def initialize(secrets)
57
+ super(secrets: secrets)
58
+ end
59
+
60
+ def message
61
+ "You have used a secret that is not in included in the secrets list: \n#{get_error_list}"
62
+ end
63
+ end
64
+
65
+ class InvalidRequiredSecretValue < NuclearSecretError
66
+ def initialize(secrets)
67
+ super(secrets: secrets)
68
+ end
69
+
70
+ def message
71
+ "You used an invalid secret: \n#{get_error_list}"
72
+ end
73
+ end
74
+
75
+ class MismatchedSecretType < NuclearSecretError
76
+ def initialize(secrets)
77
+ super(secrets: secrets)
78
+ end
79
+
80
+ def message
81
+ "You included a secret of the wrong type: \n#{get_error_list}"
82
+ end
83
+ end
84
+ end
@@ -1,3 +1,3 @@
1
1
  module NuclearSecrets
2
- VERSION = "1.0.1".freeze
2
+ VERSION = "1.0.2".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nuclear_secrets
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Atomic Jolt
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-09-13 00:00:00.000000000 Z
12
+ date: 2017-11-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -52,6 +52,7 @@ files:
52
52
  - config/initializers/nuclear_secrets.rb
53
53
  - lib/nuclear_secrets.rb
54
54
  - lib/nuclear_secrets/engine.rb
55
+ - lib/nuclear_secrets/errors.rb
55
56
  - lib/nuclear_secrets/version.rb
56
57
  homepage: https://github.com/atomicjolt/NuclearSecrets
57
58
  licenses:
@@ -73,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
74
  version: '0'
74
75
  requirements: []
75
76
  rubyforge_project:
76
- rubygems_version: 2.6.13
77
+ rubygems_version: 2.6.11
77
78
  signing_key:
78
79
  specification_version: 4
79
80
  summary: Quell rails secret espionage by verifying what secrets exist and their types