castle-rb 2.3.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +55 -9
  3. data/lib/castle.rb +17 -7
  4. data/lib/castle/api.rb +20 -22
  5. data/lib/castle/client.rb +50 -19
  6. data/lib/castle/command.rb +5 -0
  7. data/lib/castle/commands/authenticate.rb +25 -0
  8. data/lib/castle/commands/identify.rb +30 -0
  9. data/lib/castle/commands/review.rb +13 -0
  10. data/lib/castle/commands/track.rb +25 -0
  11. data/lib/castle/commands/with_context.rb +28 -0
  12. data/lib/castle/configuration.rb +46 -14
  13. data/lib/castle/context_merger.rb +13 -0
  14. data/lib/castle/default_context.rb +28 -0
  15. data/lib/castle/errors.rb +2 -0
  16. data/lib/castle/extractors/client_id.rb +4 -14
  17. data/lib/castle/extractors/headers.rb +6 -18
  18. data/lib/castle/failover_auth_response.rb +21 -0
  19. data/lib/castle/header_formatter.rb +9 -0
  20. data/lib/castle/request.rb +7 -13
  21. data/lib/castle/response.rb +2 -0
  22. data/lib/castle/review.rb +11 -0
  23. data/lib/castle/secure_mode.rb +11 -0
  24. data/lib/castle/support/hanami.rb +19 -0
  25. data/lib/castle/support/padrino.rb +1 -1
  26. data/lib/castle/support/rails.rb +1 -1
  27. data/lib/castle/support/sinatra.rb +4 -2
  28. data/lib/castle/utils.rb +55 -0
  29. data/lib/castle/utils/cloner.rb +11 -0
  30. data/lib/castle/utils/merger.rb +23 -0
  31. data/lib/castle/version.rb +1 -1
  32. data/spec/lib/castle/api_spec.rb +16 -25
  33. data/spec/lib/castle/client_spec.rb +175 -39
  34. data/spec/lib/castle/command_spec.rb +9 -0
  35. data/spec/lib/castle/commands/authenticate_spec.rb +106 -0
  36. data/spec/lib/castle/commands/identify_spec.rb +85 -0
  37. data/spec/lib/castle/commands/review_spec.rb +24 -0
  38. data/spec/lib/castle/commands/track_spec.rb +107 -0
  39. data/spec/lib/castle/configuration_spec.rb +75 -27
  40. data/spec/lib/castle/context_merger_spec.rb +34 -0
  41. data/spec/lib/castle/default_context_spec.rb +35 -0
  42. data/spec/lib/castle/extractors/client_id_spec.rb +13 -5
  43. data/spec/lib/castle/extractors/headers_spec.rb +6 -5
  44. data/spec/lib/castle/extractors/ip_spec.rb +2 -9
  45. data/spec/lib/castle/header_formatter_spec.rb +21 -0
  46. data/spec/lib/castle/request_spec.rb +12 -9
  47. data/spec/lib/castle/response_spec.rb +1 -3
  48. data/spec/lib/castle/review_spec.rb +23 -0
  49. data/spec/lib/castle/secure_mode_spec.rb +9 -0
  50. data/spec/lib/castle/utils/cloner_spec.rb +18 -0
  51. data/spec/lib/castle/utils/merger_spec.rb +13 -0
  52. data/spec/lib/castle/utils_spec.rb +156 -0
  53. data/spec/lib/castle/version_spec.rb +1 -5
  54. data/spec/lib/castle_spec.rb +8 -15
  55. data/spec/spec_helper.rb +3 -9
  56. metadata +46 -12
  57. data/lib/castle/cookie_store.rb +0 -52
  58. data/lib/castle/headers.rb +0 -39
  59. data/lib/castle/support.rb +0 -11
  60. data/lib/castle/system.rb +0 -36
  61. data/spec/lib/castle/headers_spec.rb +0 -82
  62. data/spec/lib/castle/system_spec.rb +0 -70
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Castle::Response do
6
4
  subject(:castle_response) do
7
5
  described_class.new(response)
@@ -32,8 +30,8 @@ describe Castle::Response do
32
30
  it_behaves_like 'response_failed', 404, Castle::NotFoundError
33
31
  it_behaves_like 'response_failed', 419, Castle::UserUnauthorizedError
34
32
  it_behaves_like 'response_failed', 422, Castle::InvalidParametersError
35
- it_behaves_like 'response_failed', 500, Castle::ApiError
36
33
  it_behaves_like 'response_failed', 499, Castle::ApiError
34
+ it_behaves_like 'response_failed', 500, Castle::InternalServerError
37
35
  end
38
36
 
39
37
  describe 'parse' do
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Review do
4
+ before do
5
+ stub_request(:any, /api.castle.io/).with(
6
+ basic_auth: ['', 'secret']
7
+ ).to_return(status: 200, body: '{}', headers: {})
8
+ end
9
+
10
+ context '#retrieve' do
11
+ subject(:retrieve) { described_class.retrieve(review_id) }
12
+
13
+ let(:review_id) { '1234' }
14
+
15
+ before { retrieve }
16
+
17
+ it do
18
+ assert_requested :get,
19
+ "https://api.castle.io/v1/reviews/#{review_id}",
20
+ times: 1
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::SecureMode do
4
+ it 'has signature' do
5
+ expect(described_class.signature('test')).to eql(
6
+ '0329a06b62cd16b33eb6792be8c60b158d89a2ee3a876fce9a881ebb488c0914'
7
+ )
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Utils::Cloner do
4
+ subject(:cloner) { described_class }
5
+
6
+ describe 'call' do
7
+ let(:nested) { { c: '3' } }
8
+ let(:first) { { test: { test1: { c: '4' }, test2: nested, a: '1', b: '2' } } }
9
+ let(:result) { { test: { test1: { c: '4' }, test2: { c: '3' }, a: '1', b: '2' } } }
10
+ let(:cloned) { cloner.call(first) }
11
+
12
+ before { cloned }
13
+ it do
14
+ nested[:test] = 'sample'
15
+ expect(cloned).to be_eql(result)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Utils::Merger do
4
+ subject(:merger) { described_class }
5
+
6
+ describe 'call' do
7
+ let(:first) { { test: { test1: { c: '4' }, test2: { c: '3' }, a: '1', b: '2' } } }
8
+ let(:second) { { test2: '2', test: { 'test1' => { d: '5' }, test2: '6', a: nil, b: '3' } } }
9
+ let(:result) { { test2: '2', test: { test1: { c: '4', d: '5' }, test2: '6', b: '3' } } }
10
+
11
+ it { expect(merger.call(first, second)).to be_eql(result) }
12
+ end
13
+ end
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Utils do
4
+ let(:nested_strings) { { 'a' => { 'b' => { 'c' => 3 } } } }
5
+ let(:nested_symbols) { { a: { b: { c: 3 } } } }
6
+ let(:nested_mixed) { { 'a' => { b: { 'c' => 3 } } } }
7
+ let(:string_array_of_hashes) { { 'a' => [{ 'b' => 2 }, { 'c' => 3 }, 4] } }
8
+ let(:symbol_array_of_hashes) { { a: [{ b: 2 }, { c: 3 }, 4] } }
9
+ let(:mixed_array_of_hashes) { { a: [{ b: 2 }, { 'c' => 3 }, 4] } }
10
+
11
+ context '#deep_symbolize_keys' do
12
+ subject { described_class.deep_symbolize_keys(hash) }
13
+
14
+ context 'nested_symbols' do
15
+ let(:hash) { nested_symbols }
16
+
17
+ it { is_expected.to eq(nested_symbols) }
18
+ end
19
+
20
+ context 'nested_strings' do
21
+ let(:hash) { nested_strings }
22
+
23
+ it { is_expected.to eq(nested_symbols) }
24
+ end
25
+
26
+ context 'nested_mixed' do
27
+ let(:hash) { nested_mixed }
28
+
29
+ it { is_expected.to eq(nested_symbols) }
30
+ end
31
+
32
+ context 'string_array_of_hashes' do
33
+ let(:hash) { string_array_of_hashes }
34
+
35
+ it { is_expected.to eq(symbol_array_of_hashes) }
36
+ end
37
+
38
+ context 'symbol_array_of_hashes' do
39
+ let(:hash) { symbol_array_of_hashes }
40
+
41
+ it { is_expected.to eq(symbol_array_of_hashes) }
42
+ end
43
+
44
+ context 'mixed_array_of_hashes' do
45
+ let(:hash) { mixed_array_of_hashes }
46
+
47
+ it { is_expected.to eq(symbol_array_of_hashes) }
48
+ end
49
+ end
50
+
51
+ context '#deep_symbolize_keys' do
52
+ subject { described_class.deep_symbolize_keys!(Castle::Utils::Cloner.call(hash)) }
53
+
54
+ context 'nested_symbols' do
55
+ let(:hash) { nested_symbols }
56
+
57
+ it { is_expected.to eq(nested_symbols) }
58
+ end
59
+
60
+ context 'nested_strings' do
61
+ let(:hash) { nested_strings }
62
+
63
+ it { is_expected.to eq(nested_symbols) }
64
+ end
65
+
66
+ context 'nested_mixed' do
67
+ let(:hash) { nested_mixed }
68
+
69
+ it { is_expected.to eq(nested_symbols) }
70
+ end
71
+
72
+ context 'string_array_of_hashes' do
73
+ let(:hash) { string_array_of_hashes }
74
+
75
+ it { is_expected.to eq(symbol_array_of_hashes) }
76
+ end
77
+
78
+ context 'symbol_array_of_hashes' do
79
+ let(:hash) { symbol_array_of_hashes }
80
+
81
+ it { is_expected.to eq(symbol_array_of_hashes) }
82
+ end
83
+
84
+ context 'mixed_array_of_hashes' do
85
+ let(:hash) { mixed_array_of_hashes }
86
+
87
+ it { is_expected.to eq(symbol_array_of_hashes) }
88
+ end
89
+ end
90
+
91
+ describe '::replace_invalid_characters' do
92
+ subject { described_class.replace_invalid_characters(input) }
93
+
94
+ context 'when input is a string' do
95
+ let(:input) { '1234' }
96
+
97
+ it { is_expected.to eq input }
98
+ end
99
+
100
+ context 'when input is an array' do
101
+ let(:input) { [1, 2, 3, '4'] }
102
+
103
+ it { is_expected.to eq input }
104
+ end
105
+
106
+ context 'when input is a hash' do
107
+ let(:input) { { user_id: 1 } }
108
+
109
+ it { is_expected.to eq input }
110
+ end
111
+
112
+ context 'when input is nil' do
113
+ let(:input) { nil }
114
+
115
+ it { is_expected.to eq input }
116
+ end
117
+
118
+ context 'when input is a nested hash' do
119
+ let(:input) { { user: { id: 1 } } }
120
+
121
+ it { is_expected.to eq input }
122
+ end
123
+
124
+ context 'with invalid UTF-8 characters' do
125
+ context 'when input is a hash' do
126
+ let(:input) { { user_id: "inv\xC4lid" } }
127
+
128
+ it { is_expected.to eq(user_id: 'inv�lid') }
129
+ end
130
+
131
+ context 'when input is a nested hash' do
132
+ let(:input) { { user: { id: "inv\xC4lid" } } }
133
+
134
+ it { is_expected.to eq(user: { id: 'inv�lid' }) }
135
+ end
136
+
137
+ context 'when input is an array of hashes' do
138
+ let(:input) { [{ user: "inv\xC4lid" }] * 2 }
139
+
140
+ it { is_expected.to eq([{ user: 'inv�lid' }, { user: 'inv�lid' }]) }
141
+ end
142
+
143
+ context 'when input is an array' do
144
+ let(:input) { ["inv\xC4lid"] * 2 }
145
+
146
+ it { is_expected.to eq(['inv�lid', 'inv�lid']) }
147
+ end
148
+
149
+ context 'when input is a hash with array in key' do
150
+ let(:input) { { items: ["inv\xC4lid"] * 2 } }
151
+
152
+ it { is_expected.to eq(items: ['inv�lid', 'inv�lid']) }
153
+ end
154
+ end
155
+ end
156
+ end
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Castle do
6
- it 'have version' do
7
- expect(described_class::VERSION).to match(/\d\.\d\.\d/)
8
- end
4
+ it { expect(described_class::VERSION).to match(/\d\.\d\.\d/) }
9
5
  end
@@ -1,25 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Castle do
6
4
  subject(:castle) { described_class }
7
5
 
8
6
  describe 'config' do
9
- it do
10
- expect(castle.config).to be_kind_of(Castle::Configuration)
11
- end
7
+ it { expect(castle.config).to be_kind_of(Castle::Configuration) }
12
8
  end
13
9
 
14
10
  describe 'api_secret setter' do
15
11
  let(:value) { 'new_secret' }
16
12
 
17
- before do
18
- castle.api_secret = value
19
- end
20
- it do
21
- expect(castle.config.api_secret).to be_eql(value)
22
- end
13
+ before { castle.api_secret = value }
14
+
15
+ it { expect(castle.config.api_secret).to be_eql(value) }
23
16
  end
24
17
 
25
18
  describe 'configure' do
@@ -38,14 +31,13 @@ describe Castle do
38
31
  config.request_timeout = timeout
39
32
  end
40
33
  end
34
+
41
35
  it_behaves_like 'config_setup'
42
36
  end
43
37
 
44
38
  context 'by options' do
45
- before do
46
- castle.configure(request_timeout: timeout,
47
- api_secret: value)
48
- end
39
+ before { castle.configure(request_timeout: timeout, api_secret: value) }
40
+
49
41
  it_behaves_like 'config_setup'
50
42
  end
51
43
 
@@ -55,6 +47,7 @@ describe Castle do
55
47
  config.api_secret = value
56
48
  end
57
49
  end
50
+
58
51
  it_behaves_like 'config_setup'
59
52
  end
60
53
  end
data/spec/spec_helper.rb CHANGED
@@ -4,10 +4,10 @@ require 'rubygems'
4
4
  require 'bundler/setup'
5
5
  require 'rack'
6
6
  require 'webmock/rspec'
7
- require 'pry'
7
+ require 'byebug'
8
8
 
9
- require 'simplecov'
10
- SimpleCov.start
9
+ require 'coveralls'
10
+ Coveralls.wear!
11
11
 
12
12
  require 'castle'
13
13
 
@@ -18,10 +18,4 @@ end
18
18
  WebMock.disable_net_connect!(allow_localhost: true)
19
19
 
20
20
  RSpec.configure do |config|
21
- config.before(:each) do
22
- Castle.config.api_endpoint = 'https://api.castle.io/v1'
23
- Castle.config.request_timeout = 30.0
24
- stub_request(:any, /api.castle.io/)
25
- .to_return(status: 200, body: '{}', headers: {})
26
- end
27
21
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: castle-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johan Brissmyr
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-18 00:00:00.000000000 Z
11
+ date: 2017-10-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: The easiest way to protect your users
13
+ description: Castle protects your users from account compromise
14
14
  email: johan@castle.io
15
15
  executables: []
16
16
  extensions: []
@@ -21,31 +21,54 @@ files:
21
21
  - lib/castle.rb
22
22
  - lib/castle/api.rb
23
23
  - lib/castle/client.rb
24
+ - lib/castle/command.rb
25
+ - lib/castle/commands/authenticate.rb
26
+ - lib/castle/commands/identify.rb
27
+ - lib/castle/commands/review.rb
28
+ - lib/castle/commands/track.rb
29
+ - lib/castle/commands/with_context.rb
24
30
  - lib/castle/configuration.rb
25
- - lib/castle/cookie_store.rb
31
+ - lib/castle/context_merger.rb
32
+ - lib/castle/default_context.rb
26
33
  - lib/castle/errors.rb
27
34
  - lib/castle/extractors/client_id.rb
28
35
  - lib/castle/extractors/headers.rb
29
36
  - lib/castle/extractors/ip.rb
30
- - lib/castle/headers.rb
37
+ - lib/castle/failover_auth_response.rb
38
+ - lib/castle/header_formatter.rb
31
39
  - lib/castle/request.rb
32
40
  - lib/castle/response.rb
33
- - lib/castle/support.rb
41
+ - lib/castle/review.rb
42
+ - lib/castle/secure_mode.rb
43
+ - lib/castle/support/hanami.rb
34
44
  - lib/castle/support/padrino.rb
35
45
  - lib/castle/support/rails.rb
36
46
  - lib/castle/support/sinatra.rb
37
- - lib/castle/system.rb
47
+ - lib/castle/utils.rb
48
+ - lib/castle/utils/cloner.rb
49
+ - lib/castle/utils/merger.rb
38
50
  - lib/castle/version.rb
39
51
  - spec/lib/castle/api_spec.rb
40
52
  - spec/lib/castle/client_spec.rb
53
+ - spec/lib/castle/command_spec.rb
54
+ - spec/lib/castle/commands/authenticate_spec.rb
55
+ - spec/lib/castle/commands/identify_spec.rb
56
+ - spec/lib/castle/commands/review_spec.rb
57
+ - spec/lib/castle/commands/track_spec.rb
41
58
  - spec/lib/castle/configuration_spec.rb
59
+ - spec/lib/castle/context_merger_spec.rb
60
+ - spec/lib/castle/default_context_spec.rb
42
61
  - spec/lib/castle/extractors/client_id_spec.rb
43
62
  - spec/lib/castle/extractors/headers_spec.rb
44
63
  - spec/lib/castle/extractors/ip_spec.rb
45
- - spec/lib/castle/headers_spec.rb
64
+ - spec/lib/castle/header_formatter_spec.rb
46
65
  - spec/lib/castle/request_spec.rb
47
66
  - spec/lib/castle/response_spec.rb
48
- - spec/lib/castle/system_spec.rb
67
+ - spec/lib/castle/review_spec.rb
68
+ - spec/lib/castle/secure_mode_spec.rb
69
+ - spec/lib/castle/utils/cloner_spec.rb
70
+ - spec/lib/castle/utils/merger_spec.rb
71
+ - spec/lib/castle/utils_spec.rb
49
72
  - spec/lib/castle/version_spec.rb
50
73
  - spec/lib/castle_spec.rb
51
74
  - spec/spec_helper.rb
@@ -69,21 +92,32 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
92
  version: '0'
70
93
  requirements: []
71
94
  rubyforge_project:
72
- rubygems_version: 2.6.10
95
+ rubygems_version: 2.6.14
73
96
  signing_key:
74
97
  specification_version: 4
75
98
  summary: Castle
76
99
  test_files:
77
100
  - spec/lib/castle/api_spec.rb
78
101
  - spec/lib/castle/client_spec.rb
102
+ - spec/lib/castle/command_spec.rb
103
+ - spec/lib/castle/commands/authenticate_spec.rb
104
+ - spec/lib/castle/commands/identify_spec.rb
105
+ - spec/lib/castle/commands/review_spec.rb
106
+ - spec/lib/castle/commands/track_spec.rb
79
107
  - spec/lib/castle/configuration_spec.rb
108
+ - spec/lib/castle/context_merger_spec.rb
109
+ - spec/lib/castle/default_context_spec.rb
80
110
  - spec/lib/castle/extractors/client_id_spec.rb
81
111
  - spec/lib/castle/extractors/headers_spec.rb
82
112
  - spec/lib/castle/extractors/ip_spec.rb
83
- - spec/lib/castle/headers_spec.rb
113
+ - spec/lib/castle/header_formatter_spec.rb
84
114
  - spec/lib/castle/request_spec.rb
85
115
  - spec/lib/castle/response_spec.rb
86
- - spec/lib/castle/system_spec.rb
116
+ - spec/lib/castle/review_spec.rb
117
+ - spec/lib/castle/secure_mode_spec.rb
118
+ - spec/lib/castle/utils/cloner_spec.rb
119
+ - spec/lib/castle/utils/merger_spec.rb
120
+ - spec/lib/castle/utils_spec.rb
87
121
  - spec/lib/castle/version_spec.rb
88
122
  - spec/lib/castle_spec.rb
89
123
  - spec/spec_helper.rb