locked-rb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +127 -0
  3. data/lib/locked-rb.rb +3 -0
  4. data/lib/locked.rb +60 -0
  5. data/lib/locked/api.rb +40 -0
  6. data/lib/locked/api/request.rb +37 -0
  7. data/lib/locked/api/request/build.rb +29 -0
  8. data/lib/locked/api/response.rb +40 -0
  9. data/lib/locked/client.rb +66 -0
  10. data/lib/locked/command.rb +5 -0
  11. data/lib/locked/commands/authenticate.rb +23 -0
  12. data/lib/locked/commands/identify.rb +23 -0
  13. data/lib/locked/commands/review.rb +14 -0
  14. data/lib/locked/configuration.rb +75 -0
  15. data/lib/locked/context/default.rb +40 -0
  16. data/lib/locked/context/merger.rb +14 -0
  17. data/lib/locked/context/sanitizer.rb +23 -0
  18. data/lib/locked/errors.rb +41 -0
  19. data/lib/locked/extractors/client_id.rb +17 -0
  20. data/lib/locked/extractors/headers.rb +24 -0
  21. data/lib/locked/extractors/ip.rb +18 -0
  22. data/lib/locked/failover_auth_response.rb +23 -0
  23. data/lib/locked/header_formatter.rb +9 -0
  24. data/lib/locked/review.rb +11 -0
  25. data/lib/locked/secure_mode.rb +11 -0
  26. data/lib/locked/support/hanami.rb +19 -0
  27. data/lib/locked/support/padrino.rb +19 -0
  28. data/lib/locked/support/rails.rb +13 -0
  29. data/lib/locked/support/sinatra.rb +19 -0
  30. data/lib/locked/utils.rb +55 -0
  31. data/lib/locked/utils/cloner.rb +11 -0
  32. data/lib/locked/utils/merger.rb +23 -0
  33. data/lib/locked/utils/timestamp.rb +12 -0
  34. data/lib/locked/validators/not_supported.rb +16 -0
  35. data/lib/locked/validators/present.rb +16 -0
  36. data/lib/locked/version.rb +5 -0
  37. data/spec/lib/Locked/api/request/build_spec.rb +42 -0
  38. data/spec/lib/Locked/api/request_spec.rb +59 -0
  39. data/spec/lib/Locked/api/response_spec.rb +58 -0
  40. data/spec/lib/Locked/api_spec.rb +37 -0
  41. data/spec/lib/Locked/client_spec.rb +226 -0
  42. data/spec/lib/Locked/command_spec.rb +9 -0
  43. data/spec/lib/Locked/commands/authenticate_spec.rb +95 -0
  44. data/spec/lib/Locked/commands/identify_spec.rb +87 -0
  45. data/spec/lib/Locked/commands/review_spec.rb +24 -0
  46. data/spec/lib/Locked/configuration_spec.rb +146 -0
  47. data/spec/lib/Locked/context/default_spec.rb +35 -0
  48. data/spec/lib/Locked/context/merger_spec.rb +23 -0
  49. data/spec/lib/Locked/context/sanitizer_spec.rb +27 -0
  50. data/spec/lib/Locked/extractors/client_id_spec.rb +62 -0
  51. data/spec/lib/Locked/extractors/headers_spec.rb +26 -0
  52. data/spec/lib/Locked/extractors/ip_spec.rb +27 -0
  53. data/spec/lib/Locked/header_formatter_spec.rb +25 -0
  54. data/spec/lib/Locked/review_spec.rb +19 -0
  55. data/spec/lib/Locked/secure_mode_spec.rb +9 -0
  56. data/spec/lib/Locked/utils/cloner_spec.rb +18 -0
  57. data/spec/lib/Locked/utils/merger_spec.rb +13 -0
  58. data/spec/lib/Locked/utils/timestamp_spec.rb +17 -0
  59. data/spec/lib/Locked/utils_spec.rb +156 -0
  60. data/spec/lib/Locked/validators/not_supported_spec.rb +26 -0
  61. data/spec/lib/Locked/validators/present_spec.rb +33 -0
  62. data/spec/lib/Locked/version_spec.rb +5 -0
  63. data/spec/lib/locked_spec.rb +66 -0
  64. data/spec/spec_helper.rb +22 -0
  65. metadata +133 -0
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Locked::Command do
4
+ subject(:command) { described_class.new('go', { id: '1' }, :post) }
5
+
6
+ it { expect(command.path).to be_eql('go') }
7
+ it { expect(command.data).to be_eql(id: '1') }
8
+ it { expect(command.method).to be_eql(:post) }
9
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Locked::Commands::Authenticate do
4
+ subject(:instance) { described_class.new(context) }
5
+
6
+ let(:context) { { test: { test1: '1' } } }
7
+ let(:default_payload) { { event: '$login.success', user_id: '1234', sent_at: time_auto } }
8
+
9
+ let(:time_now) { Time.now }
10
+ let(:time_auto) { time_now.utc.iso8601(3) }
11
+
12
+ before { Timecop.freeze(time_now) }
13
+ after { Timecop.return }
14
+
15
+ describe '.build' do
16
+ subject(:command) { instance.build(payload) }
17
+
18
+ context 'with simple merger' do
19
+ let(:payload) { default_payload.merge(context: { test: { test2: '1' } }) }
20
+ let(:command_data) do
21
+ default_payload.merge(context: { test: { test1: '1', test2: '1' } })
22
+ end
23
+ it { expect(command.path).to be_eql('authenticate') }
24
+ it { expect(command.data).to be_eql(command_data) }
25
+ it { expect(command.method).to be_eql(:post) }
26
+ end
27
+
28
+ context 'with properties' do
29
+ let(:payload) { default_payload.merge(properties: { test: '1' }) }
30
+ let(:command_data) do
31
+ default_payload.merge(properties: { test: '1' }, context: context)
32
+ end
33
+
34
+ it { expect(command.path).to be_eql('authenticate') }
35
+ it { expect(command.data).to be_eql(command_data) }
36
+ it { expect(command.method).to be_eql(:post) }
37
+ end
38
+
39
+ context 'with user_traits' do
40
+ let(:payload) { default_payload.merge(user_traits: { test: '1' }) }
41
+ let(:command_data) do
42
+ default_payload.merge(user_traits: { test: '1' }, context: context)
43
+ end
44
+
45
+ it { expect(command.path).to be_eql('authenticate') }
46
+ it { expect(command.data).to be_eql(command_data) }
47
+ it { expect(command.method).to be_eql(:post) }
48
+ end
49
+
50
+ context 'when active true' do
51
+ let(:payload) { default_payload.merge(context: { active: true }) }
52
+ let(:command_data) do
53
+ default_payload.merge(context: context.merge(active: true))
54
+ end
55
+
56
+ it { expect(command.path).to be_eql('authenticate') }
57
+ it { expect(command.data).to be_eql(command_data) }
58
+ it { expect(command.method).to be_eql(:post) }
59
+ end
60
+
61
+ context 'when active false' do
62
+ let(:payload) { default_payload.merge(context: { active: false }) }
63
+ let(:command_data) do
64
+ default_payload.merge(context: context.merge(active: false))
65
+ end
66
+
67
+ it { expect(command.path).to be_eql('authenticate') }
68
+ it { expect(command.data).to be_eql(command_data) }
69
+ it { expect(command.method).to be_eql(:post) }
70
+ end
71
+
72
+ context 'when active string' do
73
+ let(:payload) { default_payload.merge(context: { active: 'string' }) }
74
+ let(:command_data) { default_payload.merge(context: context) }
75
+
76
+ it { expect(command.method).to be_eql(:post) }
77
+ it { expect(command.path).to be_eql('authenticate') }
78
+ it { expect(command.data).to be_eql(command_data) }
79
+ end
80
+ end
81
+
82
+ describe '#validate!' do
83
+ subject(:validate!) { instance.build(payload) }
84
+
85
+ context 'with event not present' do
86
+ let(:payload) { {} }
87
+
88
+ it do
89
+ expect do
90
+ validate!
91
+ end.to raise_error(Locked::InvalidParametersError, 'event is missing or empty')
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Locked::Commands::Identify do
4
+ # subject(:instance) { described_class.new(context) }
5
+ #
6
+ # let(:context) { { test: { test1: '1' } } }
7
+ # let(:default_payload) { { user_id: '1234', sent_at: time_auto } }
8
+ #
9
+ # let(:time_now) { Time.now }
10
+ # let(:time_auto) { time_now.utc.iso8601(3) }
11
+ #
12
+ # before { Timecop.freeze(time_now) }
13
+ # after { Timecop.return }
14
+ #
15
+ # describe '.build' do
16
+ # subject(:command) { instance.build(payload) }
17
+ #
18
+ # context 'with simple merger' do
19
+ # let(:payload) { default_payload.merge(context: { test: { test2: '1' } }) }
20
+ # let(:command_data) do
21
+ # default_payload.merge(context: { test: { test1: '1', test2: '1' } })
22
+ # end
23
+ #
24
+ # it { expect(command.method).to be_eql(:post) }
25
+ # it { expect(command.path).to be_eql('identify') }
26
+ # it { expect(command.data).to be_eql(command_data) }
27
+ # end
28
+ #
29
+ # context 'with user_traits' do
30
+ # let(:payload) { default_payload.merge(user_traits: { test: '1' }) }
31
+ # let(:command_data) do
32
+ # default_payload.merge(user_traits: { test: '1' }, context: context)
33
+ # end
34
+ #
35
+ # it { expect(command.method).to be_eql(:post) }
36
+ # it { expect(command.path).to be_eql('identify') }
37
+ # it { expect(command.data).to be_eql(command_data) }
38
+ # end
39
+ #
40
+ # context 'when active true' do
41
+ # let(:payload) { default_payload.merge(context: { active: true }) }
42
+ # let(:command_data) do
43
+ # default_payload.merge(context: context.merge(active: true))
44
+ # end
45
+ #
46
+ # it { expect(command.method).to be_eql(:post) }
47
+ # it { expect(command.path).to be_eql('identify') }
48
+ # it { expect(command.data).to be_eql(command_data) }
49
+ # end
50
+ #
51
+ # context 'when active false' do
52
+ # let(:payload) { default_payload.merge(context: { active: false }) }
53
+ # let(:command_data) do
54
+ # default_payload.merge(context: context.merge(active: false))
55
+ # end
56
+ #
57
+ # it { expect(command.method).to be_eql(:post) }
58
+ # it { expect(command.path).to be_eql('identify') }
59
+ # it { expect(command.data).to be_eql(command_data) }
60
+ # end
61
+ #
62
+ # context 'when active string' do
63
+ # let(:payload) { default_payload.merge(context: { active: 'string' }) }
64
+ # let(:command_data) { default_payload.merge(context: context) }
65
+ #
66
+ # it { expect(command.method).to be_eql(:post) }
67
+ # it { expect(command.path).to be_eql('identify') }
68
+ # it { expect(command.data).to be_eql(command_data) }
69
+ # end
70
+ # end
71
+ #
72
+ # describe '#validate!' do
73
+ # subject(:validate!) { instance.build(payload) }
74
+ #
75
+ # context 'with user_id not present' do
76
+ # let(:payload) { {} }
77
+ #
78
+ # it { expect { validate! }.not_to raise_error }
79
+ # end
80
+ #
81
+ # context 'with user_id present' do
82
+ # let(:payload) { { user_id: '1234' } }
83
+ #
84
+ # it { expect { validate! }.not_to raise_error }
85
+ # end
86
+ # end
87
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Locked::Commands::Review do
4
+ subject(:instance) { described_class }
5
+
6
+ let(:context) { {} }
7
+ let(:review_id) { '1234' }
8
+
9
+ describe '.build' do
10
+ subject(:command) { instance.build(review_id) }
11
+
12
+ context 'without review_id' do
13
+ let(:review_id) { '' }
14
+
15
+ it { expect { command }.to raise_error(Locked::InvalidParametersError) }
16
+ end
17
+
18
+ context 'with review_id' do
19
+ it { expect(command.method).to be_eql(:get) }
20
+ it { expect(command.path).to be_eql("reviews/#{review_id}") }
21
+ it { expect(command.data).to be_nil }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Locked::Configuration do
4
+ subject(:config) do
5
+ described_class.new
6
+ end
7
+
8
+ describe 'host' do
9
+ context 'with default' do
10
+ it { expect(config.host).to be_eql('locked.jp') }
11
+ end
12
+
13
+ context 'with setter' do
14
+ before { config.host = 'locked.dev' }
15
+
16
+ it { expect(config.host).to be_eql('locked.dev') }
17
+ end
18
+ end
19
+
20
+ describe 'post' do
21
+ context 'with default' do
22
+ it { expect(config.port).to be_eql(443) }
23
+ end
24
+
25
+ context 'with setter' do
26
+ before { config.port = 3001 }
27
+
28
+ it { expect(config.port).to be_eql(3001) }
29
+ end
30
+ end
31
+
32
+ describe 'api_key' do
33
+ context 'with env' do
34
+ before do
35
+ allow(ENV).to receive(:fetch).with(
36
+ 'X_LOCKED_API_KEY', ''
37
+ ).and_return('secret_key')
38
+ end
39
+
40
+ it do
41
+ expect(config.api_key).to be_eql('secret_key')
42
+ end
43
+ end
44
+
45
+ context 'with setter' do
46
+ let(:value) { 'new_key' }
47
+
48
+ before do
49
+ config.api_key = value
50
+ end
51
+ it do
52
+ expect(config.api_key).to be_eql(value)
53
+ end
54
+ end
55
+
56
+ it do
57
+ expect(config.api_key).to be_eql('')
58
+ end
59
+ end
60
+
61
+ describe 'request_timeout' do
62
+ it do
63
+ expect(config.request_timeout).to be_eql(1000)
64
+ end
65
+
66
+ context 'with setter' do
67
+ let(:value) { 50.0 }
68
+
69
+ before do
70
+ config.request_timeout = value
71
+ end
72
+ it do
73
+ expect(config.request_timeout).to be_eql(value)
74
+ end
75
+ end
76
+ end
77
+
78
+ describe 'whitelisted' do
79
+ it do
80
+ expect(config.whitelisted.size).to be_eql(13)
81
+ end
82
+
83
+ context 'with setter' do
84
+ before do
85
+ config.whitelisted = ['header']
86
+ end
87
+ it do
88
+ expect(config.whitelisted).to be_eql(['Header'])
89
+ end
90
+ end
91
+
92
+ context 'when appending' do
93
+ before do
94
+ config.whitelisted += ['header']
95
+ end
96
+ it { expect(config.whitelisted).to be_include('Header') }
97
+ it { expect(config.whitelisted.size).to be_eql(14) }
98
+ end
99
+ end
100
+
101
+ describe 'blacklisted' do
102
+ it do
103
+ expect(config.blacklisted.size).to be_eql(1)
104
+ end
105
+
106
+ context 'with setter' do
107
+ before do
108
+ config.blacklisted = ['header']
109
+ end
110
+ it do
111
+ expect(config.blacklisted).to be_eql(['Header'])
112
+ end
113
+ end
114
+
115
+ context 'when appending' do
116
+ before do
117
+ config.blacklisted += ['header']
118
+ end
119
+ it { expect(config.blacklisted).to be_include('Header') }
120
+ it { expect(config.blacklisted.size).to be_eql(2) }
121
+ end
122
+ end
123
+
124
+ describe 'failover_strategy' do
125
+ it do
126
+ expect(config.failover_strategy).to be_eql(:deny)
127
+ end
128
+
129
+ context 'with setter' do
130
+ before do
131
+ config.failover_strategy = :deny
132
+ end
133
+ it do
134
+ expect(config.failover_strategy).to be_eql(:deny)
135
+ end
136
+ end
137
+
138
+ context 'when broken' do
139
+ it do
140
+ expect do
141
+ config.failover_strategy = :unicorn
142
+ end.to raise_error(Locked::ConfigurationError)
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Locked::Context::Default do
4
+ subject { described_class.new(request, nil) }
5
+
6
+ let(:ip) { '1.2.3.4' }
7
+ let(:cookie_id) { 'abcd' }
8
+
9
+ let(:env) do
10
+ Rack::MockRequest.env_for('/',
11
+ 'HTTP_X_FORWARDED_FOR' => ip,
12
+ 'HTTP-Accept-Language' => 'en',
13
+ 'HTTP-User-Agent' => 'test',
14
+ 'HTTP_COOKIE' => "__cid=#{cookie_id};other=efgh")
15
+ end
16
+ let(:request) { Rack::Request.new(env) }
17
+ let(:default_context) { subject.call }
18
+ let(:version) { '2.2.0' }
19
+
20
+ before do
21
+ stub_const('Locked::VERSION', version)
22
+ end
23
+
24
+ it { expect(default_context[:active]).to be_eql(true) }
25
+ it { expect(default_context[:origin]).to be_eql('web') }
26
+ it {
27
+ expect(default_context[:headers]).to be_eql(
28
+ 'X-Forwarded-For' => '1.2.3.4', 'Accept-Language' => 'en', 'User-Agent' => 'test'
29
+ )
30
+ }
31
+ it { expect(default_context[:ip]).to be_eql(ip) }
32
+ it { expect(default_context[:library][:name]).to be_eql('locked-rb') }
33
+ it { expect(default_context[:library][:version]).to be_eql(version) }
34
+ it { expect(default_context[:user_agent]).to be_eql('test') }
35
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Locked::Context::Merger do
4
+ let(:first) { { test: { test1: { c: '4' } } } }
5
+
6
+ describe '#call' do
7
+ subject { described_class.call(first, second) }
8
+
9
+ let(:result) { { test: { test1: { c: '4', d: '5' } } } }
10
+
11
+ context 'with symbol keys' do
12
+ let(:second) { { test: { test1: { d: '5' } } } }
13
+
14
+ it { is_expected.to eq(result) }
15
+ end
16
+
17
+ context 'with string keys' do
18
+ let(:second) { { 'test' => { 'test1' => { 'd' => '5' } } } }
19
+
20
+ it { is_expected.to eq(result) }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Locked::Context::Sanitizer do
4
+ let(:paylod) { { test: 'test' } }
5
+
6
+ describe '#call' do
7
+ subject { described_class.call(context) }
8
+
9
+ context 'when active true' do
10
+ let(:context) { paylod.merge(active: true) }
11
+
12
+ it { is_expected.to eql(context) }
13
+ end
14
+
15
+ context 'when active false' do
16
+ let(:context) { paylod.merge(active: false) }
17
+
18
+ it { is_expected.to eql(context) }
19
+ end
20
+
21
+ context 'when active string' do
22
+ let(:context) { paylod.merge(active: 'uknown') }
23
+
24
+ it { is_expected.to eql(paylod) }
25
+ end
26
+ end
27
+ end