complex_config 0.22.3 → 0.23.0
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 +4 -4
- data/CHANGES.md +36 -19
- data/README.md +610 -105
- data/Rakefile +6 -4
- data/VERSION +1 -1
- data/bin/complex_config +31 -1
- data/complex_config.gemspec +4 -3
- data/lib/complex_config/config.rb +46 -1
- data/lib/complex_config/encryption.rb +58 -0
- data/lib/complex_config/errors.rb +88 -0
- data/lib/complex_config/key_source.rb +32 -0
- data/lib/complex_config/provider/shortcuts.rb +34 -0
- data/lib/complex_config/provider.rb +342 -0
- data/lib/complex_config/proxy.rb +32 -0
- data/lib/complex_config/railtie.rb +5 -0
- data/lib/complex_config/settings.rb +374 -2
- data/lib/complex_config/tree.rb +93 -0
- data/lib/complex_config/version.rb +1 -1
- data/lib/complex_config.rb +13 -0
- data/spec/spec_helper.rb +4 -5
- metadata +17 -3
@@ -6,17 +6,51 @@ require 'mize'
|
|
6
6
|
require 'tins/xt/secure_write'
|
7
7
|
require 'tins/xt/ask_and_send'
|
8
8
|
|
9
|
+
# A provider class that manages configuration loading, caching, and access
|
10
|
+
#
|
11
|
+
# The Provider class serves as the central hub for accessing and managing
|
12
|
+
# configuration data within the ComplexConfig system. It handles loading
|
13
|
+
# configuration files from disk, applying environment-specific settings,
|
14
|
+
# processing plugins for dynamic attribute resolution, and providing memoized
|
15
|
+
# access to configuration data through caching mechanisms.
|
16
|
+
#
|
17
|
+
# @see ComplexConfig::Config
|
18
|
+
# @see ComplexConfig::Settings
|
19
|
+
# @see ComplexConfig::Proxy
|
20
|
+
# @see ComplexConfig::KeySource
|
21
|
+
# @see ComplexConfig::Encryption
|
9
22
|
class ComplexConfig::Provider
|
10
23
|
include Tins::SexySingleton
|
11
24
|
include ComplexConfig::Provider::Shortcuts
|
12
25
|
|
26
|
+
# Initializes a new provider instance with default settings
|
27
|
+
#
|
28
|
+
# Sets up the provider with an empty plugins collection and enables deep
|
29
|
+
# freezing by default to ensure configuration immutability.
|
13
30
|
def initialize
|
14
31
|
@plugins = Set.new
|
15
32
|
@deep_freeze = true
|
16
33
|
end
|
17
34
|
|
35
|
+
# The master_key_pathname= method sets the pathname for the master encryption
|
36
|
+
# key file
|
37
|
+
#
|
38
|
+
# This setter method allows configuring the location of the master key file
|
39
|
+
# that will be used for encryption and decryption operations throughout the
|
40
|
+
# system
|
41
|
+
#
|
42
|
+
# @attr_writer [String, nil] pathname The path to the master key file, or nil to reset
|
18
43
|
attr_writer :master_key_pathname
|
19
44
|
|
45
|
+
# The master_key_pathname method retrieves the configured master key file
|
46
|
+
# path
|
47
|
+
#
|
48
|
+
# This method returns the explicitly set master key pathname if one has been
|
49
|
+
# configured, otherwise it defaults to a 'master.key' file within the
|
50
|
+
# configuration directory
|
51
|
+
#
|
52
|
+
# @return [String, Pathname] the path to the master key file or a Pathname object
|
53
|
+
# representing the default location in the config directory
|
20
54
|
def master_key_pathname
|
21
55
|
if @master_key_pathname
|
22
56
|
@master_key_pathname
|
@@ -25,18 +59,50 @@ class ComplexConfig::Provider
|
|
25
59
|
end
|
26
60
|
end
|
27
61
|
|
62
|
+
# The configure_with method applies the given configuration to this provider
|
63
|
+
# instance
|
64
|
+
#
|
65
|
+
# This method takes a configuration object and applies its settings to the
|
66
|
+
# current provider instance It then flushes the configuration cache to ensure
|
67
|
+
# the changes take effect immediately
|
68
|
+
#
|
69
|
+
# @param config [ComplexConfig::Config] the configuration object to apply to
|
70
|
+
# this provider
|
71
|
+
# @return [self] returns self for chaining operations
|
28
72
|
def configure_with(config)
|
29
73
|
config.configure(self)
|
30
74
|
flush_cache
|
31
75
|
end
|
32
76
|
|
77
|
+
# The plugins attribute reader provides access to the set of plugins
|
78
|
+
# registered with this provider
|
79
|
+
#
|
80
|
+
# @return [Set<Proc>] the set containing all registered plugin procs
|
33
81
|
attr_reader :plugins
|
34
82
|
|
83
|
+
# The add_plugin method adds a new plugin to the provider's collection of
|
84
|
+
# plugins
|
85
|
+
#
|
86
|
+
# This method registers a plugin proc with the provider, allowing it to be
|
87
|
+
# executed when configuration attributes are accessed and no direct value is
|
88
|
+
# found
|
89
|
+
#
|
90
|
+
# @param plugin [Proc] The plugin proc to add to the provider's plugins set
|
91
|
+
# @return [self] Returns self to allow for method chaining
|
35
92
|
def add_plugin(plugin)
|
36
93
|
plugins.add plugin
|
37
94
|
self
|
38
95
|
end
|
39
96
|
|
97
|
+
# The deep_freeze= method sets the deep freezing behavior for configuration
|
98
|
+
# objects
|
99
|
+
#
|
100
|
+
# This method configures whether configuration settings should be deeply
|
101
|
+
# frozen to prevent modification after initialization. When disabling deep
|
102
|
+
# freezing, it clears the configuration cache to ensure changes take effect
|
103
|
+
# immediately.
|
104
|
+
#
|
105
|
+
# @attr_writer [Boolean] flag true to enable deep freezing, false to disable it
|
40
106
|
def deep_freeze=(flag)
|
41
107
|
if @deep_freeze && !flag
|
42
108
|
mize_cache_clear
|
@@ -44,10 +110,31 @@ class ComplexConfig::Provider
|
|
44
110
|
@deep_freeze = flag
|
45
111
|
end
|
46
112
|
|
113
|
+
# The deep_freeze? method checks whether deep freezing is enabled for
|
114
|
+
# configuration objects
|
115
|
+
#
|
116
|
+
# This method returns a boolean value indicating whether the provider has
|
117
|
+
# been configured to deeply freeze configuration settings, preventing
|
118
|
+
# modification after initialization
|
119
|
+
#
|
120
|
+
# @return [TrueClass, FalseClass] true if deep freezing is enabled, false
|
121
|
+
# otherwise
|
47
122
|
def deep_freeze?
|
48
123
|
!!@deep_freeze
|
49
124
|
end
|
50
125
|
|
126
|
+
# The apply_plugins method executes registered plugins for a given setting
|
127
|
+
# and ID
|
128
|
+
#
|
129
|
+
# This method iterates through all registered plugins and attempts to execute
|
130
|
+
# each one with the provided setting and ID. It uses catch/throw to handle
|
131
|
+
# plugin skipping behavior, returning the first non-skipped plugin result.
|
132
|
+
#
|
133
|
+
# @param setting [ComplexConfig::Settings] The settings object to apply
|
134
|
+
# plugins to
|
135
|
+
# @param id [Object] The identifier used when executing plugins
|
136
|
+
# @return [Object, nil] The result from the first applicable plugin, or nil
|
137
|
+
# if no plugin applies
|
51
138
|
def apply_plugins(setting, id)
|
52
139
|
plugins.find do |plugin|
|
53
140
|
catch :skip do
|
@@ -57,6 +144,15 @@ class ComplexConfig::Provider
|
|
57
144
|
end
|
58
145
|
end
|
59
146
|
|
147
|
+
# The config_dir= method sets the configuration directory path for the
|
148
|
+
# provider
|
149
|
+
#
|
150
|
+
# This setter method assigns a new configuration directory path to the
|
151
|
+
# provider instance, allowing it to locate configuration files at the
|
152
|
+
# specified location
|
153
|
+
#
|
154
|
+
# @attr_writer [String, nil] dir The path to the configuration directory, or nil to
|
155
|
+
# reset to default
|
60
156
|
def config_dir=(dir)
|
61
157
|
if dir.nil?
|
62
158
|
@config_dir = nil
|
@@ -65,23 +161,79 @@ class ComplexConfig::Provider
|
|
65
161
|
end
|
66
162
|
end
|
67
163
|
|
164
|
+
# The config_dir method retrieves the configuration directory path
|
165
|
+
#
|
166
|
+
# This method returns the configured configuration directory path, falling
|
167
|
+
# back to a default location based on Rails root or the current working
|
168
|
+
# directory when no explicit path is set
|
169
|
+
#
|
170
|
+
# @return [Pathname] the configuration directory path
|
68
171
|
def config_dir
|
69
172
|
@config_dir || (defined?(Rails) && Rails.respond_to?(:root) && Rails.root || Pathname.pwd) + 'config'
|
70
173
|
end
|
71
174
|
|
175
|
+
# The pathname method constructs a file path for a configuration file
|
176
|
+
#
|
177
|
+
# This method takes a configuration name and returns the full path to the
|
178
|
+
# corresponding YAML configuration file by combining the configuration
|
179
|
+
# directory with the name and file extension.
|
180
|
+
#
|
181
|
+
# @param name [String] the name of the configuration file (without extension)
|
182
|
+
# @return [Pathname] the full path to the configuration file with .yml extension
|
72
183
|
def pathname(name)
|
73
184
|
config_dir + "#{name}.yml"
|
74
185
|
end
|
75
186
|
|
187
|
+
# The decrypt_config method retrieves decrypted configuration data from an
|
188
|
+
# encrypted file
|
189
|
+
#
|
190
|
+
# @param pathname [String, Pathname] the path to the encrypted configuration
|
191
|
+
# file
|
192
|
+
#
|
193
|
+
# @return [String, nil] the decrypted configuration content if successful, or
|
194
|
+
# nil if decryption fails
|
195
|
+
#
|
196
|
+
# @see decrypt_config_case for the internal implementation that handles the
|
197
|
+
# actual decryption logic
|
76
198
|
def decrypt_config(pathname)
|
77
199
|
decrypt_config_case(pathname).first
|
78
200
|
end
|
79
201
|
|
202
|
+
# The encrypt_config method encrypts configuration data using a key source
|
203
|
+
#
|
204
|
+
# @param pathname [String, Pathname] the path to the configuration file to be
|
205
|
+
# encrypted
|
206
|
+
# @param config [Object] the configuration object to encrypt
|
207
|
+
# @return [String] the base64-encoded encrypted string including the
|
208
|
+
# encrypted data, initialization vector, and authentication tag separated by
|
209
|
+
# '--'
|
80
210
|
def encrypt_config(pathname, config)
|
81
211
|
ks = key_source(pathname)
|
82
212
|
ComplexConfig::Encryption.new(ks.key_bytes).encrypt(config)
|
83
213
|
end
|
84
214
|
|
215
|
+
# The config method reads and processes configuration data from a file
|
216
|
+
#
|
217
|
+
# This method loads configuration data from the specified file path, handling
|
218
|
+
# both plain YAML files and encrypted YAML files. It processes the
|
219
|
+
# configuration data through ERB evaluation, parses it into Ruby objects, and
|
220
|
+
# builds a Settings object with appropriate environment-specific values.
|
221
|
+
#
|
222
|
+
# @param pathname [String, Pathname] The path to the configuration file to read
|
223
|
+
# @param name [String, nil] The name to use when building the Settings object,
|
224
|
+
# or nil to derive it from the filename
|
225
|
+
# @return [ComplexConfig::Settings] A Settings object containing the parsed
|
226
|
+
# configuration data with environment-specific values
|
227
|
+
# @raise [ComplexConfig::ConfigurationFileMissing] If the configuration file
|
228
|
+
# cannot be found and no decrypted data is available
|
229
|
+
# @raise [ComplexConfig::EncryptionKeyMissing] If an encrypted configuration
|
230
|
+
# file is encountered but no encryption key is available
|
231
|
+
# @raise [ComplexConfig::ConfigurationSyntaxError] If the YAML syntax in the
|
232
|
+
# configuration file is invalid
|
233
|
+
# @raise [TypeError] If the configuration data cannot be converted to a hash
|
234
|
+
# @see decrypt_config_case for decryption logic
|
235
|
+
# @see evaluate for ERB processing
|
236
|
+
# @see ComplexConfig::Settings.build for Settings object construction
|
85
237
|
def config(pathname, name = nil)
|
86
238
|
datas = []
|
87
239
|
path_exist = File.exist?(pathname)
|
@@ -124,11 +276,40 @@ class ComplexConfig::Provider
|
|
124
276
|
raise ComplexConfig::ComplexConfigError.wrap(:ConfigurationSyntaxError, e)
|
125
277
|
end
|
126
278
|
|
279
|
+
# The [] method provides access to configuration data by name
|
280
|
+
#
|
281
|
+
# This method serves as a shortcut for retrieving configuration settings by
|
282
|
+
# their name, delegating to the config method with the appropriate pathname
|
283
|
+
# and name parameters
|
284
|
+
#
|
285
|
+
# @param name [String] the name of the configuration to retrieve
|
286
|
+
# @return [ComplexConfig::Settings] the configuration settings object for the
|
287
|
+
# specified name
|
127
288
|
def [](name)
|
128
289
|
config pathname(name), name
|
129
290
|
end
|
130
291
|
memoize method: :[]
|
131
292
|
|
293
|
+
# The write_config method writes configuration data to a file
|
294
|
+
#
|
295
|
+
# This method handles writing configuration data to either a plain YAML file
|
296
|
+
# or an encrypted file depending on the encryption settings. It supports
|
297
|
+
# storing encryption keys alongside the encrypted configuration file and
|
298
|
+
# provides options for specifying the encryption key source.
|
299
|
+
#
|
300
|
+
# @param name [String, ComplexConfig::Settings] The name of the configuration
|
301
|
+
# to write or a Settings object
|
302
|
+
# @param value [Object, nil] The configuration value to write, required when
|
303
|
+
# name is a string
|
304
|
+
# @param encrypt [Boolean, Symbol, String] Whether to encrypt the
|
305
|
+
# configuration, accepts :random, true, or a hex key string
|
306
|
+
# @param store_key [Boolean] Whether to store the encryption key in a
|
307
|
+
# separate file
|
308
|
+
#
|
309
|
+
# @return [String, Boolean] The encryption key if stored, otherwise true
|
310
|
+
# @see prepare_output for data formatting
|
311
|
+
# @see provide_key_source for key management
|
312
|
+
# @see flush_cache to clear the configuration cache after writing
|
132
313
|
def write_config(name, value: nil, encrypt: false, store_key: false)
|
133
314
|
name, value = interpret_name_value(name, value)
|
134
315
|
config_pathname = pathname(name).to_s
|
@@ -153,29 +334,81 @@ class ComplexConfig::Provider
|
|
153
334
|
flush_cache
|
154
335
|
end
|
155
336
|
|
337
|
+
# The prepare_output method converts a value into YAML format
|
338
|
+
#
|
339
|
+
# This method takes a value and transforms it into a YAML string
|
340
|
+
# representation by first converting it to a hash with string keys and then
|
341
|
+
# serializing it as YAML
|
342
|
+
#
|
343
|
+
# @param value [Object] the value to convert to YAML format
|
344
|
+
# @return [String] the YAML representation of the value
|
156
345
|
def prepare_output(value)
|
157
346
|
value.each_with_object({}) do |(k, v), h|
|
158
347
|
h[k.to_s] = v
|
159
348
|
end.to_yaml
|
160
349
|
end
|
161
350
|
|
351
|
+
# The exist? method checks whether a configuration file exists and is
|
352
|
+
# accessible
|
353
|
+
#
|
354
|
+
# @param name [String] the name of the configuration to check for existence
|
355
|
+
# @return [TrueClass, FalseClass] true if the configuration file exists and
|
356
|
+
# can be loaded, false otherwise
|
357
|
+
# @see config for the underlying configuration loading logic
|
358
|
+
# @see ComplexConfig::ConfigurationFileMissing when a configuration file is missing
|
359
|
+
# @see ComplexConfig::EncryptionKeyMissing when an encryption key is required but not available
|
162
360
|
def exist?(name)
|
163
361
|
!!config(pathname(name), name)
|
164
362
|
rescue ComplexConfig::ConfigurationFileMissing, ComplexConfig::EncryptionKeyMissing
|
165
363
|
false
|
166
364
|
end
|
167
365
|
|
366
|
+
# The proxy method creates and returns a new proxy object for dynamic
|
367
|
+
# configuration access
|
368
|
+
#
|
369
|
+
# This method instantiates a ComplexConfig::Proxy object that defers
|
370
|
+
# configuration loading until a method is first called. The proxy supports
|
371
|
+
# environment-specific configuration lookups and can handle both direct
|
372
|
+
# configuration access and existence checks.
|
373
|
+
#
|
374
|
+
# @param env [String, nil] The environment name to use for configuration lookups,
|
375
|
+
# defaults to nil which will use the default environment
|
376
|
+
# @return [ComplexConfig::Proxy] A new proxy object for dynamic configuration
|
377
|
+
# access
|
168
378
|
def proxy(env = nil)
|
169
379
|
ComplexConfig::Proxy.new(env)
|
170
380
|
end
|
171
381
|
memoize method: :proxy
|
172
382
|
|
383
|
+
# The flush_cache method clears the configuration cache and returns the
|
384
|
+
# receiver
|
385
|
+
#
|
386
|
+
# This method invalidates the cached configuration data stored in the
|
387
|
+
# provider, ensuring that subsequent configuration accesses will reload the
|
388
|
+
# data from source. It is typically used during development when
|
389
|
+
# configuration files may have changed or when explicit cache invalidation is
|
390
|
+
# required.
|
391
|
+
#
|
392
|
+
# @return [ComplexConfig::Provider] the provider instance itself for chaining operations
|
173
393
|
def flush_cache
|
174
394
|
mize_cache_clear
|
175
395
|
self
|
176
396
|
end
|
177
397
|
|
178
398
|
if RUBY_VERSION >= "3"
|
399
|
+
# The evaluate method processes ERB template data and returns the result
|
400
|
+
#
|
401
|
+
# This method takes raw configuration data that may contain ERB templating
|
402
|
+
# syntax and evaluates it using Ruby's built-in ERB processor. It sets up
|
403
|
+
# the ERB environment with appropriate trim mode and filename for proper
|
404
|
+
# error reporting before executing the template.
|
405
|
+
#
|
406
|
+
# @param pathname [String, Pathname] The path to the file being evaluated,
|
407
|
+
# used for error reporting and debugging purposes
|
408
|
+
# @param data [String] The raw configuration data string that may contain
|
409
|
+
# ERB templating syntax to be processed
|
410
|
+
# @return [String] The processed configuration data with all ERB templates
|
411
|
+
# evaluated and replaced with their actual values
|
179
412
|
def evaluate(pathname, data)
|
180
413
|
erb = ::ERB.new(data, trim_mode: '-')
|
181
414
|
erb.filename = pathname.to_s
|
@@ -189,14 +422,42 @@ class ComplexConfig::Provider
|
|
189
422
|
end
|
190
423
|
end
|
191
424
|
|
425
|
+
# The env method retrieves the current environment name for configuration
|
426
|
+
# lookups
|
427
|
+
#
|
428
|
+
# This method determines the appropriate environment to use for configuration
|
429
|
+
# access by checking various possible sources in order: an explicitly set
|
430
|
+
# instance variable, Rails environment if available, the RAILS_ENV
|
431
|
+
# environment variable, or falling back to 'development' as the default
|
432
|
+
#
|
433
|
+
# @return [String] the name of the current environment
|
192
434
|
def env
|
193
435
|
@env || defined?(Rails) && Rails.respond_to?(:env) && Rails.env ||
|
194
436
|
ENV['RAILS_ENV'] ||
|
195
437
|
'development'
|
196
438
|
end
|
197
439
|
|
440
|
+
# The env= method sets the environment name for configuration lookups
|
441
|
+
#
|
442
|
+
# This setter method assigns a new environment value to the provider
|
443
|
+
# instance, which will be used when accessing configuration data that
|
444
|
+
# supports environment-specific values.
|
445
|
+
#
|
446
|
+
# @attr_writer [String, nil] env The environment name to use for configuration
|
447
|
+
# lookups, or nil to reset to the default environment
|
198
448
|
attr_writer :env
|
199
449
|
|
450
|
+
# The key_source method retrieves an encryption key from configured sources
|
451
|
+
#
|
452
|
+
# This method attempts to find a valid encryption key by checking multiple
|
453
|
+
# possible sources in a specific order until one provides a usable key. It
|
454
|
+
# prioritizes keys from instance variables, file paths, environment
|
455
|
+
# variables, and master key files.
|
456
|
+
#
|
457
|
+
# @param pathname [String, nil] The path to a configuration file that may
|
458
|
+
# contain a key
|
459
|
+
# @return [ComplexConfig::KeySource, nil] A KeySource object containing the
|
460
|
+
# first valid key found, or nil if no key is available
|
200
461
|
def key_source(pathname = nil)
|
201
462
|
[
|
202
463
|
ComplexConfig::KeySource.new(var: @key),
|
@@ -207,16 +468,49 @@ class ComplexConfig::Provider
|
|
207
468
|
].find(&:key)
|
208
469
|
end
|
209
470
|
|
471
|
+
# The key method retrieves an encryption key from configured sources
|
472
|
+
#
|
473
|
+
# This method obtains an encryption key by delegating to the key_source
|
474
|
+
# method with the provided pathname, then extracts the actual key value from
|
475
|
+
# the returned KeySource object
|
476
|
+
#
|
477
|
+
# @param pathname [String, nil] The path to a configuration file that may
|
478
|
+
# contain a key
|
479
|
+
# @return [String, nil] The encryption key as a string if found, or nil if no
|
480
|
+
# key is available
|
210
481
|
def key(pathname = nil)
|
211
482
|
key_source(pathname).ask_and_send(:key)
|
212
483
|
end
|
213
484
|
|
485
|
+
# The key= method sets the encryption key for the provider
|
486
|
+
#
|
487
|
+
# This setter method assigns a new encryption key value to the provider
|
488
|
+
# instance, which will be used for encrypting and decrypting configuration
|
489
|
+
# data.
|
490
|
+
#
|
491
|
+
# @attr_writer [String, nil] key The encryption key to use, or nil to clear the key
|
214
492
|
attr_writer :key
|
215
493
|
|
494
|
+
# The new_key method generates a random encryption key
|
495
|
+
#
|
496
|
+
# This method creates a secure random key suitable for encryption purposes by
|
497
|
+
# generating a hexadecimal string of 32 characters (16 bytes).
|
498
|
+
#
|
499
|
+
# @return [String] a randomly generated hexadecimal encryption key
|
216
500
|
def new_key
|
217
501
|
SecureRandom.hex(16)
|
218
502
|
end
|
219
503
|
|
504
|
+
# The valid_key? method checks whether a given key is valid for encryption
|
505
|
+
# purposes
|
506
|
+
#
|
507
|
+
# This method attempts to validate an encryption key by creating a KeySource
|
508
|
+
# object with the provided key and then trying to instantiate an Encryption
|
509
|
+
# object with it to verify the key's format and validity
|
510
|
+
#
|
511
|
+
# @param key [String] the encryption key to validate
|
512
|
+
# @return [ComplexConfig::KeySource, FalseClass] returns the KeySource object
|
513
|
+
# if the key is valid, false otherwise
|
220
514
|
def valid_key?(key)
|
221
515
|
ks = ComplexConfig::KeySource.new(var: key)
|
222
516
|
ComplexConfig::Encryption.new(ks.key_bytes)
|
@@ -227,6 +521,20 @@ class ComplexConfig::Provider
|
|
227
521
|
|
228
522
|
private
|
229
523
|
|
524
|
+
# The decrypt_config_case method handles the decryption of encrypted
|
525
|
+
# configuration files
|
526
|
+
#
|
527
|
+
# This method checks for the existence of an encrypted configuration file and
|
528
|
+
# attempts to decrypt it using the available key source. It returns different
|
529
|
+
# status codes based on whether the decryption was successful, if a key was
|
530
|
+
# missing, or if the file itself was missing.
|
531
|
+
#
|
532
|
+
# @param pathname [String, Pathname] The path to the configuration file to
|
533
|
+
# check for encryption
|
534
|
+
#
|
535
|
+
# @return [Array] An array containing the decrypted data (or nil), a symbol
|
536
|
+
# indicating the result status (:ok, :key_missing, or :file_missing), and
|
537
|
+
# the encrypted file's pathname
|
230
538
|
def decrypt_config_case(pathname)
|
231
539
|
enc_pathname = pathname.to_s + '.enc'
|
232
540
|
my_ks = key_source(pathname)
|
@@ -242,6 +550,24 @@ class ComplexConfig::Provider
|
|
242
550
|
return nil, :file_missing, enc_pathname
|
243
551
|
end
|
244
552
|
|
553
|
+
# The interpret_name_value method processes name and value parameters for
|
554
|
+
# configuration handling
|
555
|
+
#
|
556
|
+
# This method normalizes the input parameters for configuration operations by
|
557
|
+
# validating the name parameter type and preparing the value parameter
|
558
|
+
# accordingly. It handles different input scenarios including
|
559
|
+
# ComplexConfig::Settings objects and string/symbol names.
|
560
|
+
#
|
561
|
+
# @param name [String, Symbol, ComplexConfig::Settings] The name parameter
|
562
|
+
# which can be a string, symbol, or ComplexConfig::Settings object
|
563
|
+
# @param value [Object, nil] The value parameter to be processed, typically a
|
564
|
+
# hash or nil
|
565
|
+
#
|
566
|
+
# @return [Array<String, Object>] An array containing the normalized name and
|
567
|
+
# value parameters for further configuration processing
|
568
|
+
#
|
569
|
+
# @raise [ArgumentError] if the name parameter is not a string/symbol or
|
570
|
+
# ComplexConfig::Settings object
|
245
571
|
def interpret_name_value(name, value)
|
246
572
|
if ComplexConfig::Settings === name
|
247
573
|
if value
|
@@ -258,6 +584,22 @@ class ComplexConfig::Provider
|
|
258
584
|
return name, value
|
259
585
|
end
|
260
586
|
|
587
|
+
# The provide_key_source method determines and returns an appropriate key
|
588
|
+
# source for encryption operations
|
589
|
+
#
|
590
|
+
# This method analyzes the encryption parameter and constructs a suitable key
|
591
|
+
# source object based on whether a random key should be generated, an
|
592
|
+
# existing key source should be used, or a specific hex key string was
|
593
|
+
# provided
|
594
|
+
#
|
595
|
+
# @param pathname [String, nil] The path to a configuration file that may
|
596
|
+
# contain a key
|
597
|
+
# @param encrypt [Boolean, Symbol, String] Encryption directive that
|
598
|
+
# determines key source selection
|
599
|
+
# @return [ComplexConfig::KeySource] A key source object configured with the
|
600
|
+
# appropriate encryption key
|
601
|
+
# @raise [ComplexConfig::EncryptionKeyInvalid] if the encryption key is
|
602
|
+
# missing or has invalid format
|
261
603
|
def provide_key_source(pathname, encrypt)
|
262
604
|
ks =
|
263
605
|
case encrypt
|
data/lib/complex_config/proxy.rb
CHANGED
@@ -1,22 +1,54 @@
|
|
1
1
|
module ComplexConfig
|
2
|
+
# A proxy class that provides dynamic configuration access with lazy
|
3
|
+
# evaluation
|
4
|
+
#
|
5
|
+
# The Proxy class acts as a wrapper around configuration access, deferring
|
6
|
+
# the actual configuration loading until a method is first called. It
|
7
|
+
# supports environment-specific configuration lookups and can handle both
|
8
|
+
# direct configuration access and existence checks.
|
9
|
+
#
|
10
|
+
# @attr_reader [String, nil] env The environment name used for configuration
|
11
|
+
# lookups
|
2
12
|
class Proxy < BasicObject
|
13
|
+
# The proxy object's initialization method sets up the environment for
|
14
|
+
# configuration access.
|
15
|
+
#
|
16
|
+
# @param env [String, nil] The environment name to use for configuration
|
17
|
+
# lookups, defaults to nil which will use the default environment
|
3
18
|
def initialize(env = nil)
|
4
19
|
@env = env
|
5
20
|
end
|
6
21
|
|
22
|
+
# The to_s method returns a string representation of the proxy object.
|
23
|
+
#
|
24
|
+
# @return [String] the string 'ComplexConfig::Proxy'
|
7
25
|
def to_s
|
8
26
|
'ComplexConfig::Proxy'
|
9
27
|
end
|
10
28
|
|
29
|
+
# The inspect method returns a string representation of the proxy object.
|
30
|
+
#
|
31
|
+
# @return [String] a string representation in the format "#<ComplexConfig::Proxy>"
|
11
32
|
def inspect
|
12
33
|
"#<#{to_s}>"
|
13
34
|
end
|
14
35
|
|
36
|
+
# The reload method flushes the configuration cache and returns the
|
37
|
+
# receiver.
|
38
|
+
#
|
39
|
+
# @return [ComplexConfig::Proxy] the proxy object itself
|
15
40
|
def reload
|
16
41
|
::ComplexConfig::Provider.flush_cache
|
17
42
|
self
|
18
43
|
end
|
19
44
|
|
45
|
+
# The method_missing method handles dynamic configuration access and
|
46
|
+
# validation.
|
47
|
+
#
|
48
|
+
# @param name [Symbol] The name of the method being called
|
49
|
+
# @param args [Array] Arguments passed to the method
|
50
|
+
#
|
51
|
+
# @return [Object] The result of the dynamic configuration lookup or method call
|
20
52
|
def method_missing(name, *args)
|
21
53
|
if name =~ /\?\z/
|
22
54
|
method_name, name = name, $`
|
@@ -1,4 +1,9 @@
|
|
1
1
|
module ComplexConfig
|
2
|
+
# Rails integration for ComplexConfig
|
3
|
+
#
|
4
|
+
# Provides integration with Rails application lifecycle by flushing the
|
5
|
+
# configuration cache during the to_prepare callback, ensuring that
|
6
|
+
# configuration changes are picked up correctly in development mode.
|
2
7
|
class Railtie < Rails::Railtie
|
3
8
|
config.to_prepare do
|
4
9
|
ComplexConfig::Provider.flush_cache
|