locked-rb 0.0.1

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.
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