sexy_settings 0.0.1 → 0.0.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.
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'sensitive_data_protector'
3
+ module SexySettings
4
+ # This module holds print methods
5
+ module Printable
6
+ def as_formatted_text(which = :all)
7
+ props_list = property_list(which)
8
+ max_key_size = props_list.map { |el| el.first.to_s.size }.max
9
+ [
10
+ sharp_line(which),
11
+ title(which),
12
+ sharp_line(which),
13
+ '',
14
+ formatted_properties(props_list, max_key_size),
15
+ ''
16
+ ].join("\n")
17
+ end
18
+
19
+ private
20
+
21
+ def sharp_line(which)
22
+ '#' * title(which).size
23
+ end
24
+
25
+ def title(which)
26
+ "##{' ' * 20}#{which.to_s.capitalize} Settings#{' ' * 21}#"
27
+ end
28
+
29
+ def indent(space_count = nil)
30
+ ' ' * (space_count.nil? ? 2 : space_count)
31
+ end
32
+
33
+ def property_list(which)
34
+ case which
35
+ when :all then @all
36
+ when :custom then @custom
37
+ when :default then @default
38
+ else ''
39
+ end.to_a
40
+ end
41
+
42
+ def formatted_properties(data, max_key_size)
43
+ data.sort_by(&:first).map do |(prop, value)|
44
+ value = protect_sensitive_data(prop, value)
45
+ "#{indent}#{prop}#{indent + indent(max_key_size - prop.to_s.size)}=#{indent}#{value}"
46
+ end
47
+ end
48
+
49
+ def protect_sensitive_data(prop, value)
50
+ SensitiveDataProtector.new(prop, value).protected_value
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ module SexySettings
3
+ # This class holds logic sensitive data hiding
4
+ class SensitiveDataProtector
5
+ PROTECTED_PROPERTIES = [/pass(\z|word)/i, /_key\z/i, /secret/i, /token/i].freeze
6
+ URL_REGEXP = %r{\A(?:https?|ftp):\/\/(?:(?<userpass>.+)@)?.*:?(?:[^\/]*)}i
7
+ attr_reader :prop, :value
8
+
9
+ def initialize(prop, value)
10
+ @prop = prop
11
+ @value = value.to_s
12
+ end
13
+
14
+ def protected_value
15
+ return hide_protected_data_in_url(value) if /_url\z/ =~ prop
16
+ return value unless PROTECTED_PROPERTIES.any? { |el| el =~ prop }
17
+ hide_protected_data(value)
18
+ end
19
+
20
+ def hide_protected_data(value)
21
+ return value if value.nil?
22
+ return '********' if value.to_s.size <= 4
23
+ "********#{value.to_s[-4..-1]}"
24
+ end
25
+
26
+ def hide_protected_data_in_url(value)
27
+ return value if value.nil? || !(URL_REGEXP =~ value)
28
+ userpass = URL_REGEXP.match(value)[:userpass]
29
+ return value if userpass.nil? || userpass.empty?
30
+ value.sub(userpass, protected_userpass(userpass))
31
+ end
32
+
33
+ def protected_userpass(value)
34
+ value.split(':', 2).compact.map(&method(:hide_protected_data)).join(':')
35
+ end
36
+ end
37
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SexySettings
2
- VERSION = "0.0.1"
3
+ VERSION = '0.0.2'
3
4
  end
data/lib/sexy_settings.rb CHANGED
@@ -1,6 +1,5 @@
1
+ # frozen_string_literal: true
1
2
  require 'sexy_settings/version'
2
3
  require 'sexy_settings/configuration'
3
4
  require 'sexy_settings/base'
4
5
  require 'sexy_settings/core'
5
-
6
-
@@ -1,20 +1,23 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "sexy_settings/version"
2
+ # frozen_string_literal: true
3
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
4
+ require 'sexy_settings/version'
4
5
 
5
6
  Gem::Specification.new do |s|
6
- s.name = "sexy_settings"
7
+ s.name = 'sexy_settings'
7
8
  s.version = SexySettings::VERSION
8
- s.authors = ["Roman Parashchenko"]
9
- s.email = ["romikoops1@gmail.com"]
10
- s.homepage = "https://github.com/romikoops/sexy_settings"
11
- s.summary = %q{Flexible specifying of application settings}
12
- s.description = %q{Library for flexible specifying of application settings different ways}
13
- s.rubyforge_project = "sexy_settings"
9
+ s.authors = ['Roman Parashchenko']
10
+ s.email = ['romikoops1@gmail.com']
11
+ s.homepage = 'https://github.com/romikoops/sexy_settings'
12
+ s.summary = 'Flexible specifying of application settings'
13
+ s.description = 'Library for flexible specifying of application settings different ways'
14
+ s.rubyforge_project = 'sexy_settings'
14
15
 
15
16
  s.files = `git ls-files`.split("\n")
16
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
- s.require_paths = ["lib"]
19
- s.add_development_dependency 'rspec'
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+ s.add_development_dependency 'rspec', '~>3.5'
21
+ s.add_development_dependency('rake')
22
+ s.add_development_dependency('yard')
20
23
  end
@@ -1,3 +1,16 @@
1
- default_property: default DEFAULT value
2
- overwritten_property: default OVERWRITTEN value
3
- console_property: default CONSOLE value
1
+ default_property: default DEFAULT value
2
+ overwritten_property: default OVERWRITTEN value
3
+ console_property: default CONSOLE value
4
+ pass: 123
5
+ user_pass: hello:world
6
+ api_key: '12341234123222333'
7
+ password_confirmation: 'mysuperpass'
8
+ passenger_name: 'Ivan Petrov'
9
+ api_token: wer221wfqw23ef
10
+ my_secret: ssdf3fvqww
11
+ email: user@example.com
12
+ test1_url: http://${email}:${user_pass}@host:80/wd/hub
13
+ test2_url: http://${email}@host/wd/hub
14
+ test3_url: http://:${user_pass}@host:80/wd/hub
15
+ test4_url:
16
+ test5_url: http://host/wd/hub
@@ -1,2 +1,2 @@
1
- overwritten_property: overwritten OVERWRITTEN value
1
+ overwritten_property: overwritten OVERWRITTEN value
2
2
  console_property: overwritten CONSOLE value
@@ -1,120 +1,140 @@
1
- require 'spec_helper'
2
-
3
- describe 'Base' do
4
- before :all do
5
- SexySettings.configure do |config|
6
- config.path_to_default_settings = File.expand_path("config.yaml", File.join(File.dirname(__FILE__), '..', '_config'))
7
- config.path_to_custom_settings = File.expand_path("overwritten.yaml", File.join(File.dirname(__FILE__), '..', '_config'))
8
- config.path_to_project = File.dirname(__FILE__)
9
- config.env_variable_with_options = 'OPTIONS'
10
- end
11
- if ENV.has_key?(SexySettings.configuration.env_variable_with_options)
12
- @original_options = ENV[SexySettings.configuration.env_variable_with_options]
13
- else
14
- @original_options = nil
15
- end
16
- ENV[SexySettings.configuration.env_variable_with_options] = "console_property=console CONSOLE value"
17
- @settings ||= settings
18
- end
19
-
20
- after :all do
21
- @original_options = ENV[SexySettings.configuration.env_variable_with_options]
22
- unless @original_options
23
- ENV[SexySettings.configuration.env_variable_with_options] = @original_options
24
- end
25
- end
26
-
27
- it "should be singleton object" do
28
- SexySettings::Base.respond_to?(:instance).should be_true
29
- SexySettings::Base.instance.is_a?(SexySettings::Base).should be_true
30
- end
31
-
32
- it "should have getter for default setting" do
33
- @settings.respond_to?(:default).should be_true
34
- expected_default_settings = {
35
- "default_property" => "default DEFAULT value",
36
- "overwritten_property" => "default OVERWRITTEN value",
37
- "console_property" => "default CONSOLE value"
38
- }
39
- @settings.default.should == expected_default_settings
40
- end
41
-
42
- it "should have getter for custom setting" do
43
- @settings.respond_to?(:default).should be_true
44
- expected_custom_settings = {
45
- "overwritten_property" => "overwritten OVERWRITTEN value",
46
- "console_property" => "overwritten CONSOLE value"
47
- }
48
- @settings.custom.should == expected_custom_settings
49
- end
50
-
51
- it "should have getter for all setting" do
52
- @settings.respond_to?(:default).should be_true
53
- expected_all_settings = {
54
- "default_property" => "default DEFAULT value",
55
- "overwritten_property" => "overwritten OVERWRITTEN value",
56
- "console_property" => "console CONSOLE value"
57
- }
58
- @settings.all.should == expected_all_settings
59
- end
60
-
61
- it "should return specified pretty formatted settings for output" do
62
- expected = <<-eos
63
- #######################################################
64
- # All Settings #
65
- #######################################################
66
-
67
- console_property = console CONSOLE value
68
- default_property = default DEFAULT value
69
- overwritten_property = overwritten OVERWRITTEN value
70
- eos
71
- @settings.as_formatted_text.should == expected
72
- end
73
-
74
- context "command line" do
75
- before :all do
76
- SexySettings.configure.env_variable_with_options = 'OPTS'
77
- ENV['OPTS'] = "string=Test, int=1, float=1.09, boolean_true=true, boolean_false=false, symbol=:foo, reference = ${string}"
78
- @clone_settings = settings.class.clone.instance
79
- end
80
-
81
- after :all do
82
- SexySettings.configure.env_variable_with_options = 'OPTIONS'
83
- end
84
-
85
- it "should convert command line string value to String type" do
86
- @clone_settings.string.should == 'Test'
87
- end
88
-
89
- it "should convert command line integer value to Fixnum type" do
90
- @clone_settings.int.should == 1
91
- @clone_settings.int.class.should == Fixnum
92
- end
93
-
94
- it "should convert command line float value to Float type" do
95
- @clone_settings.float.should == 1.09
96
- @clone_settings.float.class.should == Float
97
- end
98
-
99
- it "should convert command line true value to TrueClass type" do
100
- @clone_settings.boolean_true.should be_true
101
- end
102
-
103
- it "should convert command line false value to FalseClass type" do
104
- @clone_settings.boolean_false.should be_false
105
- @clone_settings.boolean_false.class.should == FalseClass
106
- end
107
-
108
- it "should convert command line symbol value to Symbol type" do
109
- @clone_settings.symbol.should == :foo
110
- end
111
-
112
- it "should replace command line reference to correct value" do
113
- @clone_settings.reference == 'Test'
114
- end
115
- end
116
- end
117
-
118
- def settings
119
- SexySettings::Base.instance()
120
- end
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe 'Base' do
5
+ before :all do
6
+ SexySettings.configure do |config|
7
+ config.path_to_default_settings =
8
+ File.expand_path('config.yaml', File.join(File.dirname(__FILE__), '..', '_config'))
9
+ config.path_to_custom_settings =
10
+ File.expand_path('overwritten.yaml', File.join(File.dirname(__FILE__), '..', '_config'))
11
+ config.path_to_project = File.dirname(__FILE__)
12
+ config.env_variable_with_options = 'OPTIONS'
13
+ end
14
+ @original_options = if ENV.key?(SexySettings.configuration.env_variable_with_options)
15
+ ENV[SexySettings.configuration.env_variable_with_options]
16
+ else
17
+ nil
18
+ end
19
+ ENV[SexySettings.configuration.env_variable_with_options] = 'console_property=console CONSOLE value'
20
+ @settings ||= settings
21
+ end
22
+
23
+ after :all do
24
+ @original_options = ENV[SexySettings.configuration.env_variable_with_options]
25
+ unless @original_options
26
+ ENV[SexySettings.configuration.env_variable_with_options] = @original_options
27
+ end
28
+ end
29
+
30
+ it 'should be singleton object' do
31
+ expect(SexySettings::Base.respond_to?(:instance)).to be_truthy
32
+ expect(SexySettings::Base.instance).to be_a(SexySettings::Base)
33
+ end
34
+
35
+ it 'should have getter for default setting' do
36
+ expect(@settings).to be_respond_to(:default)
37
+ expected_default_settings = {
38
+ 'default_property' => 'default DEFAULT value',
39
+ 'overwritten_property' => 'default OVERWRITTEN value',
40
+ 'console_property' => 'default CONSOLE value'
41
+ }
42
+ expect(@settings.default).to include(expected_default_settings)
43
+ end
44
+
45
+ it 'should have getter for custom setting' do
46
+ expect(@settings).to be_respond_to(:default)
47
+ expected_custom_settings = {
48
+ 'overwritten_property' => 'overwritten OVERWRITTEN value',
49
+ 'console_property' => 'overwritten CONSOLE value'
50
+ }
51
+ expect(@settings.custom).to eq(expected_custom_settings)
52
+ end
53
+
54
+ it 'should have getter for all setting' do
55
+ expect(@settings).to be_respond_to(:default)
56
+ expected_all_settings = {
57
+ 'default_property' => 'default DEFAULT value',
58
+ 'overwritten_property' => 'overwritten OVERWRITTEN value',
59
+ 'console_property' => 'console CONSOLE value'
60
+ }
61
+
62
+ expect(@settings.all).to include(expected_all_settings)
63
+ end
64
+
65
+ it 'should return specified pretty formatted settings for output' do
66
+ # rubocop:disable Lint/EmptyInterpolation
67
+ expected = <<-eos
68
+ #######################################################
69
+ # All Settings #
70
+ #######################################################
71
+
72
+ api_key = ********2333
73
+ api_token = ********23ef
74
+ console_property = console CONSOLE value
75
+ default_property = default DEFAULT value
76
+ email = user@example.com
77
+ my_secret = ********vqww
78
+ overwritten_property = overwritten OVERWRITTEN value
79
+ pass = ********
80
+ passenger_name = Ivan Petrov
81
+ password_confirmation = ********pass
82
+ test1_url = http://********.com:********orld@host:80/wd/hub
83
+ test2_url = http://********.com@host/wd/hub
84
+ test3_url = http://********:********orld@host:80/wd/hub
85
+ test4_url = #{}
86
+ test5_url = http://host/wd/hub
87
+ user_pass = ********orld
88
+ eos
89
+ # rubocop:enable Lint/EmptyInterpolation
90
+ expect(@settings.as_formatted_text).to eq(expected)
91
+ end
92
+
93
+ context 'command line' do
94
+ let(:clone_settings) { settings.class.clone.instance }
95
+ before do
96
+ SexySettings.configure.env_variable_with_options = 'SEXY_SETTINGS'
97
+ ENV['SEXY_SETTINGS'] = 'string=Test, int=1, float=1.09, boolean_true=true,' \
98
+ ' boolean_false=false, symbol=:foo, reference = ${string}'
99
+ end
100
+
101
+ after do
102
+ SexySettings.configure.env_variable_with_options = 'OPTIONS'
103
+ end
104
+
105
+ it 'should convert command line string value to String type' do
106
+ expect(clone_settings.string).to eq('Test')
107
+ end
108
+
109
+ it 'should convert command line integer value to Fixnum type' do
110
+ expect(clone_settings.int).to eq(1)
111
+ expect(clone_settings.int.class).to eq(Fixnum)
112
+ end
113
+
114
+ it 'should convert command line float value to Float type' do
115
+ expect(clone_settings.float).to eq(1.09)
116
+ expect(clone_settings.float.class).to eq(Float)
117
+ end
118
+
119
+ it 'should convert command line true value to TrueClass type' do
120
+ expect(clone_settings.boolean_true).to be_truthy
121
+ end
122
+
123
+ it 'should convert command line false value to FalseClass type' do
124
+ expect(clone_settings.boolean_false).to be_falsy
125
+ expect(clone_settings.boolean_false.class).to eq(FalseClass)
126
+ end
127
+
128
+ it 'should convert command line symbol value to Symbol type' do
129
+ expect(clone_settings.symbol).to eq(:foo)
130
+ end
131
+
132
+ it 'should replace command line reference to correct value' do
133
+ expect(clone_settings.reference).to eq('Test')
134
+ end
135
+ end
136
+ end
137
+
138
+ def settings
139
+ SexySettings::Base.instance
140
+ end
@@ -1,34 +1,46 @@
1
- require 'spec_helper'
2
-
3
- describe 'Configuration' do
4
- before :all do
5
- @expected_opts = {
6
- :path_to_default_settings => "default.yml",
7
- :path_to_custom_settings => "custom.yml",
8
- :path_to_project => '.',
9
- :env_variable_with_options => 'OPTS',
10
- :cmd_line_option_delimiter => ','
11
- }
12
- @config = SexySettings::Configuration.new
13
- end
14
-
15
- it "should have correct default options" do
16
- SexySettings::Configuration.constants.should include(:DEFAULT_OPTIONS)
17
- SexySettings::Configuration::DEFAULT_OPTIONS.should == @expected_opts
18
- end
19
-
20
- it "should have setters for all options" do
21
- @expected_opts.keys.each{|key| @config.respond_to?("#{key}=").should be_true}
22
- end
23
-
24
- it "should return last value of specified option" do
25
- new_value = 'fake'
26
- @expected_opts.keys.each{|key| @config.send("#{key}=", new_value)}
27
- @expected_opts.keys.each{|key| @config.send(key).should == new_value}
28
- end
29
-
30
- it "should return default value of specified option" do
31
- config = SexySettings::Configuration.new
32
- @expected_opts.keys.each{|key| config.send(key).should == @expected_opts[key]}
33
- end
34
- end
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ describe 'Configuration' do
5
+ let(:expected_opts) do
6
+ {
7
+ path_to_default_settings: 'default.yml',
8
+ path_to_custom_settings: 'custom.yml',
9
+ path_to_project: '.',
10
+ env_variable_with_options: 'SEXY_SETTINGS',
11
+ cmd_line_option_delimiter: ','
12
+ }
13
+ end
14
+ let(:config) { SexySettings::Configuration.new }
15
+
16
+ it 'should have correct default options' do
17
+ expect(SexySettings::Configuration.constants).to include(:DEFAULT_OPTIONS)
18
+ expect(SexySettings::Configuration::DEFAULT_OPTIONS).to eq(expected_opts)
19
+ end
20
+
21
+ it 'should have setters for all options' do
22
+ expected_opts.keys.each { |key| expect(config).to be_respond_to("#{key}=") }
23
+ end
24
+
25
+ it 'should return last value of specified option' do
26
+ new_value = 'fake'
27
+ expected_opts.keys.each do |key|
28
+ config.send("#{key}=", new_value)
29
+ expect(config.send(key)).to eq(new_value)
30
+ end
31
+ end
32
+
33
+ it 'should return default value of specified option' do
34
+ expected_opts.keys.each { |key| expect(config.send(key)).to eq(expected_opts[key]) }
35
+ end
36
+
37
+ context 'when SEXY_SETTINGS_DELIMITER env variable specified' do
38
+ before { ENV['SEXY_SETTINGS_DELIMITER'] = '$' }
39
+ after { ENV['SEXY_SETTINGS_DELIMITER'] = nil }
40
+
41
+ it 'should override specified delimiter' do
42
+ config.cmd_line_option_delimiter = ';'
43
+ expect(config.cmd_line_option_delimiter).to eq('$')
44
+ end
45
+ end
46
+ end
@@ -1,31 +1,32 @@
1
- require 'spec_helper'
2
-
3
- describe 'Core' do
4
- it "should have ability to reset settings" do
5
- new_delim = '#@#'
6
- old_delim = nil
7
- SexySettings.configure do |config|
8
- old_delim = config.cmd_line_option_delimiter
9
- config.cmd_line_option_delimiter = new_delim
10
- end
11
- SexySettings.configuration.cmd_line_option_delimiter.should ==(new_delim)
12
- SexySettings.reset
13
- SexySettings.configuration.cmd_line_option_delimiter.should ==(old_delim)
14
- end
15
-
16
- it "should return the same configuration object each time" do
17
- config = SexySettings.configuration
18
- config.is_a?(SexySettings::Configuration).should be_true
19
- config.object_id.should == SexySettings.configuration.object_id
20
- end
21
-
22
- it "should have ability to configure Configuration object with block" do
23
- SexySettings.configure do |config|
24
- config.is_a?(SexySettings::Configuration).should be_true
25
- end
26
- end
27
-
28
- it "should have ability to configure Configuration object without block" do
29
- SexySettings.configure.is_a?(SexySettings::Configuration).should be_true
30
- end
31
- end
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ describe 'Core' do
5
+ it 'should have ability to reset settings' do
6
+ new_delim = '#@#'
7
+ old_delim = nil
8
+ SexySettings.configure do |config|
9
+ old_delim = config.cmd_line_option_delimiter
10
+ config.cmd_line_option_delimiter = new_delim
11
+ end
12
+ expect(SexySettings.configuration.cmd_line_option_delimiter).to eq(new_delim)
13
+ SexySettings.reset
14
+ expect(SexySettings.configuration.cmd_line_option_delimiter).to eq(old_delim)
15
+ end
16
+
17
+ it 'should return the same configuration object each time' do
18
+ config = SexySettings.configuration
19
+ expect(config).to be_a(SexySettings::Configuration)
20
+ expect(config.object_id).to eq(SexySettings.configuration.object_id)
21
+ end
22
+
23
+ it 'should have ability to configure Configuration object with block' do
24
+ SexySettings.configure do |config|
25
+ expect(config).to be_a(SexySettings::Configuration)
26
+ end
27
+ end
28
+
29
+ it 'should have ability to configure Configuration object without block' do
30
+ expect(SexySettings.configure).to be_a(SexySettings::Configuration)
31
+ end
32
+ end
@@ -1,8 +1,9 @@
1
- require 'spec_helper'
2
-
3
- describe 'Version' do
4
- it "should contains VERSION constant with correct format" do
5
- SexySettings.constants.should include(:VERSION)
6
- SexySettings::VERSION.should match(/^\d+\.\d+\.\d+$/)
7
- end
8
- end
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ describe 'Version' do
5
+ it 'should contains VERSION constant with correct format' do
6
+ expect(SexySettings.constants).to include(:VERSION)
7
+ expect(SexySettings::VERSION).to match(/^\d+\.\d+\.\d+$/)
8
+ end
9
+ end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,2 @@
1
- require 'sexy_settings'
1
+ # frozen_string_literal: true
2
+ require 'sexy_settings'