kreds 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4fa30f22ae5af3cd8d3cfbc20b59eacabe4c2b79db4033feca2e4e89740d27aa
4
- data.tar.gz: 42a758a1e6b4c04d3a87f2d3320da866d6bda9355119cbcda77cee5d1e36881e
3
+ metadata.gz: 256854440242a87fc2debc95c8c7cda4c2c8fb836946179eccba3d8946863b25
4
+ data.tar.gz: 05c8465b2e8ab5a16f8b94cef84b85b074d5153bd60a143bd20719b0645b48e0
5
5
  SHA512:
6
- metadata.gz: 0c406cca1bd875a184c0a0c2dc00e8d42865ae62eae6e5d820a344e06873ef399e1f7455239f3918c5a4ed75cec32a8c77c2c1597a54c3b36f6674d1e181a7af
7
- data.tar.gz: 8ddcfa759c8b22eaebfe5ffc55bdac6ba63bebb316faa1dc18609a5eabf6c7e35531a76c6399f8ecee9fe0e6f8c67753885beb57ffbe3e115bf9b5d8417d1164
6
+ metadata.gz: ea580b8a4dca8c842c7e6f9c84a678cac94b3136b084dc1c91cb8c44b73d69077532441138c4a9c8bd91f84aec8c80bbb5919a27313cc18cb20d6d2df838bc6d
7
+ data.tar.gz: a36ab8f0fe482843697cc96e28c903f08a61e35d0554bf56e696a06b4116af25ab8bb546fc546d2fa781bc37d1b137501f122224059dba298269d2128cd3bfac
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## v1.1.2
2
+
3
+ - Added input validation using `dry-types` for user-facing API
4
+ - Internal code optimizations
5
+
1
6
  ## v1.1.1
2
7
 
3
8
  - Updated gemspec metadata to include the correct homepage URL
data/README.md CHANGED
@@ -1,27 +1,56 @@
1
- # Kreds
1
+ # Kreds: Streamlined Rails Credentials Access
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/kreds.svg)](http://badge.fury.io/rb/kreds)
4
4
  [![Github Actions badge](https://github.com/brownboxdev/kreds/actions/workflows/ci.yml/badge.svg)](https://github.com/brownboxdev/kreds/actions/workflows/ci.yml)
5
5
 
6
- Kreds is a simpler, shorter, and safer way to access Rails credentials, with a few additional features built in. Rails credentials are a convenient way to store secrets, but retrieving them could be more intuitive — thats where Kreds comes in.
6
+ Kreds is a simpler, shorter, and safer way to access Rails credentials, with a few extra features built in. Rails credentials are a convenient way to store secrets, but retrieving them could be more intuitive — that's where Kreds comes in.
7
7
 
8
- Instead of writing:
8
+ **Key Features:**
9
+
10
+ - Simplified credential access with clear error messages
11
+ - Environment variable fallback support
12
+ - Environment-scoped credentials access (production, staging, development)
13
+ - Automatic blank value detection and prevention
14
+
15
+ **Before and After:**
9
16
 
10
17
  ```ruby
18
+ # Instead of this (long, silent failures if value is missing):
11
19
  Rails.application.credentials[:recaptcha][:site_key]
12
- ```
20
+ # => nil
13
21
 
14
- You can simply use:
22
+ # Or this (long, unclear errors):
23
+ Rails.application.credentials[:captcha][:site_key]
24
+ # => undefined method `[]' for nil:NilClass (NoMethodError)
15
25
 
16
- ```ruby
26
+ # Or even this (longer, still unclear errors):
27
+ Rails.application.credentials.fetch(:recaptcha).fetch(:key)
28
+ # => key not found: :key (KeyError)
29
+
30
+ # You can write this (shorter, human-readable errors):
17
31
  Kreds.fetch!(:recaptcha, :site_key)
32
+ # => Blank value in credentials: [:recaptcha][:site_key] (Kreds::BlankCredentialsError)
33
+ Kreds.fetch!(:captcha, :site_key)
34
+ # => Credentials key not found: [:captcha] (Kreds::UnknownCredentialsError)
18
35
  ```
19
36
 
20
- This not only shortens your code but also ensures an exception is raised if a key is missing or a value is blank — with a clear, human-readable error message.
37
+ ## Table of Contents
38
+
39
+ **Gem Usage:**
40
+ - [Installation](#installation)
41
+ - [Credential Fetching](#credential-fetching)
42
+ - [Environment-Scoped Credentials](#environment-scoped-credentials)
43
+ - [Environment Variables](#environment-variables)
44
+ - [Debug and Inspection](#debug-and-inspection)
45
+
46
+ **Community Resources:**
47
+ - [Contributing](#contributing)
48
+ - [License](#license)
49
+ - [Code of Conduct](#code-of-conduct)
21
50
 
22
51
  ## Installation
23
52
 
24
- Add this line to your application's Gemfile:
53
+ Add Kreds to your Gemfile:
25
54
 
26
55
  ```ruby
27
56
  gem "kreds"
@@ -29,98 +58,115 @@ gem "kreds"
29
58
 
30
59
  And then execute:
31
60
 
32
- ```shell
61
+ ```bash
33
62
  bundle install
34
63
  ```
35
64
 
36
- ## Usage
37
-
38
- ### Fetch from credentials
65
+ ## Credential Fetching
39
66
 
40
- ```ruby
41
- Kreds.fetch!(:aws, :s3, :credentials, :access_key_id)
42
- ```
43
-
44
- If you make a typo, such as writing `access_key` instead of `access_key_id`, Kreds will raise `Kreds::UnknownCredentialsError` with the message: `Credentials key not found: [:aws][:s3][:credentials][:access_key]`.
67
+ **`Kreds.fetch!(*keys, var: nil, &block)`**
45
68
 
46
- Similarly, if you add an extra key that doesn’t exist: `Kreds.fetch!(:aws, :s3, :credentials, :access_key_id, :id)`, Kreds will raise `Kreds::UnknownCredentialsError` with the message: `Credentials key not found: [:aws][:s3][:credentials][:access_key_id][:id]`.
69
+ Fetches credentials from the Rails credentials store.
47
70
 
48
- If all keys are correct but the value is blank, Kreds will raise `Kreds::BlankCredentialsError` with the message: `Blank value in credentials: [:aws][:s3][:credentials][:access_key_id]`.
71
+ **Parameters:**
72
+ - `*keys` - Variable number of symbols representing the key path
73
+ - `var` - Optional environment variable name as fallback
74
+ - `&block` - Optional block to execute if fetch fails
49
75
 
50
- ### Fallback to environment variables
76
+ **Returns:** The credential value
51
77
 
52
- You can optionally provide a fallback environment variable:
78
+ **Raises:**
79
+ - `Kreds::UnknownCredentialsError` - if the key path doesn't exist
80
+ - `Kreds::BlankCredentialsError` - if the value exists but is blank
53
81
 
54
82
  ```ruby
55
- Kreds.fetch!(:aws, :s3, :credentials, :access_key_id, var: "AWS_ACCESS_KEY_ID")
56
- ```
83
+ # Basic usage
84
+ Kreds.fetch!(:aws, :s3, :credentials, :access_key_id)
57
85
 
58
- If the key is missing or blank in credentials, Kreds will attempt to fetch the value from the specified environment variable.
86
+ # With environment variable fallback
87
+ Kreds.fetch!(:aws, :access_key_id, var: "AWS_ACCESS_KEY_ID")
59
88
 
60
- If both sources are missing or blank, a combined error is raised.
89
+ # With block
90
+ Kreds.fetch!(:api_key) do
91
+ raise MyCustomError, "API key not configured"
92
+ end
93
+ ```
61
94
 
62
- ### Directly fetch from environment variable
95
+ ## Environment-Scoped Credentials
63
96
 
64
- You can also fetch directly from an environment variable:
97
+ **`Kreds.env_fetch!(*keys, var: nil, &block)`**
65
98
 
66
- ```ruby
67
- Kreds.var!("AWS_ACCESS_KEY_ID")
68
- ```
99
+ Fetches credentials scoped by the current Rails environment (e.g., `:production`, `:staging`, `:development`).
69
100
 
70
- This raises `Kreds::UnknownEnvironmentVariableError` if the variable is missing, and `Kreds::BlankEnvironmentVariableError` if it is present but the value is blank.
101
+ **Parameters:** Same as `fetch!`
71
102
 
72
- ### Fetch per Rails environment
103
+ **Returns:** The credential value from `Rails.application.credentials[Rails.env]` followed by the provided key path
73
104
 
74
- If your credentials are scoped by Rails environment (e.g., `:production`, `:staging`, `:development`), you can fetch keys under the current environment using:
105
+ **Raises:** Same exceptions as `fetch!`
75
106
 
76
107
  ```ruby
108
+ # Looks in credentials[:production][:recaptcha][:site_key] in production
77
109
  Kreds.env_fetch!(:recaptcha, :site_key)
78
110
  ```
79
111
 
80
- This will look for the key in `Rails.application.credentials[Rails.env]`. For example, in the `production` environment, it will look for `Rails.application.credentials[:production][:recaptcha][:site_key]`, and raise the same errors if the key is missing or the value is blank.
112
+ ## Environment Variables
81
113
 
82
- You can also provide an optional fallback environment variable:
114
+ **`Kreds.var!(name, &block)`**
83
115
 
84
- ```ruby
85
- Kreds.env_fetch!(:recaptcha, :site_key, var: "RECAPTCHA_SITE_KEY")
86
- ```
116
+ Fetches a value directly from environment variables.
117
+
118
+ **Parameters:**
119
+ - `name` - Environment variable name
120
+ - `&block` - Optional block to execute if variable is missing/blank
87
121
 
88
- ### Pass a block on failure
122
+ **Returns:** The environment variable value
89
123
 
90
- You can pass a block to `fetch!`, `env_fetch!`, and `var!`, which will be executed if the method fails to retrieve the value.
124
+ **Raises:**
125
+ - `Kreds::UnknownEnvironmentVariableError` - if the variable doesn't exist
126
+ - `Kreds::BlankEnvironmentVariableError` - if the variable exists but is blank
91
127
 
92
128
  ```ruby
93
- Kreds.fetch!(:aws, :s3, :credentials, :access_key_id) do
94
- raise MyCustomError, "Custom error message"
95
- end
129
+ # Direct environment variable access
130
+ Kreds.var!("AWS_ACCESS_KEY_ID")
96
131
 
132
+ # With block
97
133
  Kreds.var!("THREADS") { 1 }
98
134
  ```
99
135
 
100
- ### Show credentials
136
+ ## Debug and Inspection
101
137
 
102
- To inspect all credentials as a hash:
138
+ **`Kreds.show`**
139
+
140
+ Useful for debugging and exploring available credentials in the Rails console.
141
+
142
+ **Returns:** Hash containing all credentials
103
143
 
104
144
  ```ruby
105
145
  Kreds.show
146
+ # => { aws: { access_key_id: "...", secret_access_key: "..." }, ... }
106
147
  ```
107
148
 
108
- Useful for debugging or working in the Rails console.
109
-
110
- ## Problems?
111
-
112
- Facing a problem or want to suggest an enhancement?
113
-
114
- - **Open a Discussion**: If you have a question, experience difficulties using the gem, or have a suggestion for improvements, feel free to use the Discussions section.
115
-
116
- Encountered a bug?
117
-
118
- - **Create an Issue**: If you've identified a bug, please create an issue. Be sure to provide detailed information about the problem, including the steps to reproduce it.
119
- - **Contribute a Solution**: Found a fix for the issue? Feel free to create a pull request with your changes.
120
-
121
149
  ## Contributing
122
150
 
123
- Before creating an issue or a pull request, please read the [contributing guidelines](https://github.com/brownboxdev/kreds/blob/master/CONTRIBUTING.md).
151
+ ### Getting Help
152
+ Have a question or need assistance? Open a discussion in our [discussions section](https://github.com/brownboxdev/kreds/discussions) for:
153
+ - Usage questions
154
+ - Implementation guidance
155
+ - Feature suggestions
156
+
157
+ ### Reporting Issues
158
+ Found a bug? Please [create an issue](https://github.com/brownboxdev/kreds/issues) with:
159
+ - A clear description of the problem
160
+ - Steps to reproduce the issue
161
+ - Your environment details (Rails version, Ruby version, etc.)
162
+
163
+ ### Contributing Code
164
+ Ready to contribute? You can:
165
+ - Fix bugs by submitting pull requests
166
+ - Improve documentation
167
+ - Add new features (please discuss first in our [discussions section](https://github.com/brownboxdev/kreds/discussions))
168
+
169
+ Before contributing, please read the [contributing guidelines](https://github.com/brownboxdev/kreds/blob/master/CONTRIBUTING.md)
124
170
 
125
171
  ## License
126
172
 
data/kreds.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.homepage = "https://github.com/brownboxdev/kreds"
8
8
  spec.metadata["homepage_uri"] = spec.homepage
9
9
  spec.metadata["source_code_uri"] = spec.homepage
10
- spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
10
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
11
11
  spec.metadata["rubygems_mfa_required"] = "true"
12
12
  spec.summary = "The missing shorthand for Rails credentials"
13
13
  spec.license = "MIT"
@@ -19,5 +19,6 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.require_paths = ["lib"]
21
21
 
22
+ spec.add_dependency "dry-types", "~> 1.8"
22
23
  spec.add_dependency "rails", ">= 7.1", "< 8.1"
23
24
  end
data/lib/kreds/fetch.rb CHANGED
@@ -1,82 +1,59 @@
1
1
  module Kreds
2
2
  module Fetch
3
3
  def fetch!(*keys, var: nil, &)
4
- validate_keys!(keys)
5
- validate_var!(var)
4
+ symbolized_keys = Kreds::Inputs.process(keys, as: :symbol_array)
6
5
 
7
6
  path = []
8
7
 
9
- keys.reduce(Rails.application.credentials) do |hash, key|
8
+ symbolized_keys.reduce(Kreds.show) do |hash, key|
10
9
  path << key
11
- fetch_key(hash, key, path, keys)
10
+ fetch_key(hash, key, path, symbolized_keys)
12
11
  end
13
12
  rescue Kreds::BlankCredentialsError, Kreds::UnknownCredentialsError => e
14
- fallback_to_var(e, var, &)
13
+ fallback_to_var(e, Kreds::Inputs.process(var, as: :string, optional: true), &)
15
14
  end
16
15
 
17
16
  def env_fetch!(*keys, var: nil, &)
18
- fetch!(Rails.env, *keys, var: var, &)
17
+ fetch!(Rails.env, *keys, var:, &)
19
18
  end
20
19
 
21
20
  def var!(var, &)
22
- validate_var!(var)
21
+ value = ENV.fetch(Kreds::Inputs.process(var, as: :string))
23
22
 
24
- result, success = check_var(var)
23
+ return raise_or_yield(Kreds::BlankEnvironmentVariableError.new("Blank value in environment variable: #{var.inspect}"), &) if value.blank?
25
24
 
26
- return result if success
27
-
28
- raise_or_yield(result, &)
25
+ value
26
+ rescue KeyError
27
+ raise_or_yield(Kreds::UnknownEnvironmentVariableError.new("Environment variable not found: #{var.inspect}"), &)
29
28
  end
30
29
 
31
30
  private
32
31
 
33
- def validate_keys!(keys)
34
- raise Kreds::InvalidArgumentError, "No keys provided" if keys.empty?
35
-
36
- return if keys.all? { _1.is_a?(Symbol) || _1.is_a?(String) }
37
-
38
- raise Kreds::InvalidArgumentError, "Credentials Key must be a Symbol or a String"
39
- end
40
-
41
- def validate_var!(var)
42
- raise Kreds::InvalidArgumentError, "Environment variable must be a String" if var.present? && !var.is_a?(String)
43
- end
44
-
45
32
  def fetch_key(hash, key, path, keys)
46
- value = hash.fetch(key.to_sym)
33
+ value = hash.fetch(key)
47
34
 
48
- raise Kreds::BlankCredentialsError, "Blank value in credentials: [:#{path.join("][:")}]" if value.blank?
49
- raise Kreds::UnknownCredentialsError, "Credentials key not found: [:#{path.join("][:")}][:#{keys[path.size]}]" if !value.is_a?(Hash) && keys != path
35
+ raise Kreds::BlankCredentialsError, "Blank value in credentials: #{path_to_s(path)}" if value.blank?
36
+ raise Kreds::UnknownCredentialsError, "Credentials key not found: #{path_to_s(path)}[:#{keys[path.size]}]" unless value.is_a?(Hash) || keys == path
50
37
 
51
38
  value
52
39
  rescue KeyError
53
- raise Kreds::UnknownCredentialsError, "Credentials key not found: [:#{path.join("][:")}]"
40
+ raise Kreds::UnknownCredentialsError, "Credentials key not found: #{path_to_s(path)}"
54
41
  end
55
42
 
56
43
  def fallback_to_var(error, var, &)
57
- if var.present?
58
- result, success = check_var(var)
59
-
60
- return result if success
44
+ return raise_or_yield(error, &) if var.blank?
61
45
 
62
- raise_or_yield(Kreds::Error.new([error.message, result.message].join(", ")), &)
63
- end
64
-
65
- raise_or_yield(error, &)
66
- end
67
-
68
- def check_var(var)
69
- value = ENV.fetch(var)
70
-
71
- return [Kreds::BlankEnvironmentVariableError.new("Blank value in environment variable: #{var.inspect}"), false] if value.blank?
72
-
73
- [value, true]
74
- rescue KeyError
75
- [Kreds::UnknownEnvironmentVariableError.new("Environment variable not found: #{var.inspect}"), false]
46
+ var!(var, &)
47
+ rescue Kreds::BlankEnvironmentVariableError, Kreds::UnknownEnvironmentVariableError => e
48
+ raise_or_yield(Kreds::Error.new("#{error.message}, #{e.message}"), &)
76
49
  end
77
50
 
78
51
  def raise_or_yield(error, &)
79
52
  block_given? ? yield : raise(error)
80
53
  end
54
+
55
+ def path_to_s(path)
56
+ "[:#{path.join("][:")}]"
57
+ end
81
58
  end
82
59
  end
@@ -0,0 +1,28 @@
1
+ require "dry-types"
2
+
3
+ module Kreds
4
+ module Inputs
5
+ extend self
6
+
7
+ include Dry.Types()
8
+
9
+ TYPES = {
10
+ symbol_array: -> { self::Array.of(self::Coercible::Symbol).constrained(min_size: 1) },
11
+ string: -> { self::Strict::String },
12
+ boolean: -> { self::Strict::Bool }
13
+ }.freeze
14
+
15
+ def process(value, as:, optional: false)
16
+ checker = type_for(as)
17
+ checker = checker.optional if optional
18
+
19
+ checker[value]
20
+ rescue Dry::Types::CoercionError => e
21
+ raise Kreds::InvalidArgumentError, e
22
+ end
23
+
24
+ private
25
+
26
+ def type_for(name) = Kreds::Inputs::TYPES.fetch(name).call
27
+ end
28
+ end
data/lib/kreds/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Kreds
2
- VERSION = "1.1.1"
2
+ VERSION = "1.1.2"
3
3
  end
data/lib/kreds.rb CHANGED
@@ -2,6 +2,7 @@ require_relative "kreds/version"
2
2
 
3
3
  require "rails"
4
4
 
5
+ require_relative "kreds/inputs"
5
6
  require_relative "kreds/fetch"
6
7
  require_relative "kreds/show"
7
8
 
@@ -13,6 +14,6 @@ module Kreds
13
14
  class UnknownCredentialsError < Error; end
14
15
  class UnknownEnvironmentVariableError < Error; end
15
16
 
16
- extend ::Kreds::Fetch
17
17
  extend ::Kreds::Show
18
+ extend ::Kreds::Fetch
18
19
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kreds
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - enjaku4
@@ -9,6 +9,20 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: dry-types
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.8'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.8'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: rails
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -39,6 +53,7 @@ files:
39
53
  - kreds.gemspec
40
54
  - lib/kreds.rb
41
55
  - lib/kreds/fetch.rb
56
+ - lib/kreds/inputs.rb
42
57
  - lib/kreds/show.rb
43
58
  - lib/kreds/version.rb
44
59
  homepage: https://github.com/brownboxdev/kreds
@@ -47,7 +62,7 @@ licenses:
47
62
  metadata:
48
63
  homepage_uri: https://github.com/brownboxdev/kreds
49
64
  source_code_uri: https://github.com/brownboxdev/kreds
50
- changelog_uri: https://github.com/brownboxdev/kreds/blob/main/CHANGELOG.md
65
+ changelog_uri: https://github.com/brownboxdev/kreds/blob/master/CHANGELOG.md
51
66
  rubygems_mfa_required: 'true'
52
67
  rdoc_options: []
53
68
  require_paths: