class ComplexConfig::Provider
Attributes
env[W]
key[W]
master_key_pathname[W]
plugins[R]
Public Class Methods
new()
click to toggle source
# File lib/complex_config/provider.rb, line 13 def initialize @plugins = Set.new @deep_freeze = true end
Public Instance Methods
[](name)
click to toggle source
# File lib/complex_config/provider.rb, line 127 def [](name) config pathname(name), name end
add_plugin(plugin)
click to toggle source
# File lib/complex_config/provider.rb, line 35 def add_plugin(plugin) plugins.add plugin self end
apply_plugins(setting, id)
click to toggle source
# File lib/complex_config/provider.rb, line 51 def apply_plugins(setting, id) plugins.find do |plugin| catch :skip do value = setting.instance_exec(id, &plugin) and return value end nil end end
config(pathname, name = nil)
click to toggle source
# File lib/complex_config/provider.rb, line 85 def config(pathname, name = nil) datas = [] path_exist = File.exist?(pathname) if path_exist datas << IO.binread(pathname) end decrypted, reason, enc_pathname = decrypt_config_case(pathname) case reason when :ok datas << decrypted when :key_missing datas.empty? and raise ComplexConfig::EncryptionKeyMissing, "encryption key for #{enc_pathname.to_s.inspect} is missing" when :file_missing datas.empty? and raise ComplexConfig::ConfigurationFileMissing, "configuration file #{pathname.to_s.inspect} is missing" end results = datas.map { |d| evaluate(pathname, d) } hashes = if ::Psych::VERSION < "4" results.map { |r| ::YAML.load(r, pathname) } else results.map { |r| ::YAML.unsafe_load(r, filename: pathname) } end settings = ComplexConfig::Settings.build(name, hashes.shift) hashes.each { |h| settings.attributes_update(h) } if shared = settings.shared? shared = shared.to_h settings.each do |key, value| if value.is_a? ComplexConfig::Settings value.attributes_update_if_nil(shared) elsif value.nil? settings[key] = ComplexConfig::Settings.build(nil, shared.dup) end end end deep_freeze? and settings.deep_freeze settings rescue ::Psych::SyntaxError => e raise ComplexConfig::ComplexConfigError.wrap(:ConfigurationSyntaxError, e) end
config_dir()
click to toggle source
# File lib/complex_config/provider.rb, line 68 def config_dir @config_dir || (defined?(Rails) && Rails.respond_to?(:root) && Rails.root || Pathname.pwd) + 'config' end
config_dir=(dir)
click to toggle source
# File lib/complex_config/provider.rb, line 60 def config_dir=(dir) if dir.nil? @config_dir = nil else @config_dir = Pathname.new(dir) end end
configure_with(config)
click to toggle source
# File lib/complex_config/provider.rb, line 28 def configure_with(config) config.configure(self) flush_cache end
decrypt_config(pathname)
click to toggle source
# File lib/complex_config/provider.rb, line 76 def decrypt_config(pathname) decrypt_config_case(pathname).first end
deep_freeze=(flag)
click to toggle source
# File lib/complex_config/provider.rb, line 40 def deep_freeze=(flag) if @deep_freeze && !flag mize_cache_clear end @deep_freeze = flag end
deep_freeze?()
click to toggle source
# File lib/complex_config/provider.rb, line 47 def deep_freeze? !!@deep_freeze end
encrypt_config(pathname, config)
click to toggle source
# File lib/complex_config/provider.rb, line 80 def encrypt_config(pathname, config) ks = key_source(pathname) ComplexConfig::Encryption.new(ks.key_bytes).encrypt(config) end
env()
click to toggle source
# File lib/complex_config/provider.rb, line 192 def env @env || defined?(Rails) && Rails.respond_to?(:env) && Rails.env || ENV['RAILS_ENV'] || 'development' end
evaluate(pathname, data)
click to toggle source
# File lib/complex_config/provider.rb, line 179 def evaluate(pathname, data) erb = ::ERB.new(data, trim_mode: '-') erb.filename = pathname.to_s erb.result end
exist?(name)
click to toggle source
# File lib/complex_config/provider.rb, line 162 def exist?(name) !!config(pathname(name), name) rescue ComplexConfig::ConfigurationFileMissing, ComplexConfig::EncryptionKeyMissing false end
flush_cache()
click to toggle source
# File lib/complex_config/provider.rb, line 173 def flush_cache mize_cache_clear self end
key(pathname = nil)
click to toggle source
# File lib/complex_config/provider.rb, line 210 def key(pathname = nil) key_source(pathname).ask_and_send(:key) end
key_source(pathname = nil)
click to toggle source
# File lib/complex_config/provider.rb, line 200 def key_source(pathname = nil) [ ComplexConfig::KeySource.new(var: @key), ComplexConfig::KeySource.new(pathname: pathname), ComplexConfig::KeySource.new(env_var: 'COMPLEX_CONFIG_KEY'), ComplexConfig::KeySource.new(env_var: 'RAILS_MASTER_KEY'), ComplexConfig::KeySource.new(master_key_pathname: master_key_pathname), ].find(&:key) end
master_key_pathname()
click to toggle source
# File lib/complex_config/provider.rb, line 20 def master_key_pathname if @master_key_pathname @master_key_pathname else config_dir + 'master.key' end end
new_key()
click to toggle source
# File lib/complex_config/provider.rb, line 218 def new_key SecureRandom.hex(16) end
pathname(name)
click to toggle source
# File lib/complex_config/provider.rb, line 72 def pathname(name) config_dir + "#{name}.yml" end
prepare_output(value)
click to toggle source
# File lib/complex_config/provider.rb, line 156 def prepare_output(value) value.each_with_object({}) do |(k, v), h| h[k.to_s] = v end.to_yaml end
proxy(env = nil)
click to toggle source
# File lib/complex_config/provider.rb, line 168 def proxy(env = nil) ComplexConfig::Proxy.new(env) end
valid_key?(key)
click to toggle source
# File lib/complex_config/provider.rb, line 222 def valid_key?(key) ks = ComplexConfig::KeySource.new(var: key) ComplexConfig::Encryption.new(ks.key_bytes) ks rescue false end
write_config(name, value: nil, encrypt: false, store_key: false)
click to toggle source
# File lib/complex_config/provider.rb, line 132 def write_config(name, value: nil, encrypt: false, store_key: false) name, value = interpret_name_value(name, value) config_pathname = pathname(name).to_s if encrypt ks = provide_key_source(config_pathname, encrypt) File.secure_write(config_pathname + '.enc') do |out| out.write ComplexConfig::Encryption.new(ks.key_bytes).encrypt(prepare_output(value)) end if store_key File.secure_write(config_pathname + '.key') do |out| out.write ks.key end end ks.key else File.secure_write(config_pathname) do |out| out.puts prepare_output(value) end true end ensure flush_cache end
Private Instance Methods
decrypt_config_case(pathname)
click to toggle source
# File lib/complex_config/provider.rb, line 232 def decrypt_config_case(pathname) enc_pathname = pathname.to_s + '.enc' my_ks = key_source(pathname) if File.exist?(enc_pathname) if my_ks.ask_and_send(:key) text = IO.binread(enc_pathname) decrypted = ComplexConfig::Encryption.new(my_ks.key_bytes).decrypt(text) return decrypted, :ok, enc_pathname else return nil, :key_missing, enc_pathname end end return nil, :file_missing, enc_pathname end
interpret_name_value(name, value)
click to toggle source
# File lib/complex_config/provider.rb, line 247 def interpret_name_value(name, value) if ComplexConfig::Settings === name if value name = name.name_prefix else value = name.to_h name = name.name_prefix end elsif name.respond_to?(:to_sym) value = value.to_h else raise ArgumentError, "name has to be either string/symbol or ComplexConfig::Settings" end return name, value end
provide_key_source(pathname, encrypt)
click to toggle source
# File lib/complex_config/provider.rb, line 263 def provide_key_source(pathname, encrypt) ks = case encrypt when :random ComplexConfig::KeySource.new(var: new_key) when true key_source(pathname) when String if encrypt =~ /\A\h{32}\z/ ComplexConfig::KeySource.new(var: encrypt) else raise ComplexConfig::EncryptionKeyInvalid, "encryption key has wrong format, has to be hex number of length "\ "32, was #{encrypt.inspect}" end end ks or raise ComplexConfig::EncryptionKeyInvalid, "encryption key is missing" end