castle-rb 2.3.2 → 3.0.0

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