sexy_settings 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'