1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/activesupport/lib/active_support/encrypted_configuration.rb
Alex Ghiculescu 94d1d52c03 Allow access to nested secrets by method calls
In a new Rails app, the generated credentials file contains an example of some [nested secrets](f95c0b7e96/railties/lib/rails/generators/rails/credentials/credentials_generator.rb (L46)).

Currently you can't access them nicely the way you would top level secrets:

```
2.7.3 :001 > Rails.application.credentials.aws
 => {:access_key_id=>123, :secret_access_key=>345}
2.7.3 :002 > Rails.application.credentials.aws.access_key_id
Traceback (most recent call last):
        1: from (irb):2
NoMethodError (undefined method `access_key_id' for {:access_key_id=>123, :secret_access_key=>345}:Hash)
2.7.3 :003 > Rails.application.credentials.secret_key_base
 => "abcd..."
```

It would make secrets easier to use if you could, so this PR adds support for that. `Rails.application.credentials.aws.access_key_id` will now return `123` in the above example.
2021-04-29 14:30:43 -05:00

49 lines
1.3 KiB
Ruby

# frozen_string_literal: true
require "yaml"
require "active_support/encrypted_file"
require "active_support/ordered_options"
require "active_support/core_ext/object/inclusion"
require "active_support/core_ext/module/delegation"
module ActiveSupport
class EncryptedConfiguration < EncryptedFile
delegate :[], :fetch, to: :config
delegate_missing_to :options
def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
super content_path: config_path, key_path: key_path,
env_key: env_key, raise_if_missing_key: raise_if_missing_key
end
# Allow a config to be started without a file present
def read
super
rescue ActiveSupport::EncryptedFile::MissingContentError
""
end
def write(contents)
deserialize(contents)
super
end
def config
@config ||= deserialize(read).deep_symbolize_keys
end
private
def deep_transform(hash)
hash.transform_values { |value| value.is_a?(Hash) ? ActiveSupport::InheritableOptions.new(deep_transform(value)) : value }
end
def options
@options ||= ActiveSupport::InheritableOptions.new(deep_transform(config))
end
def deserialize(config)
YAML.load(config).presence || {}
end
end
end