castle-rb 4.2.1 → 7.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 (144) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +160 -45
  3. data/lib/castle.rb +49 -28
  4. data/lib/castle/api.rb +21 -14
  5. data/lib/castle/api/approve_device.rb +20 -0
  6. data/lib/castle/api/authenticate.rb +37 -0
  7. data/lib/castle/api/end_impersonation.rb +24 -0
  8. data/lib/castle/api/filter.rb +37 -0
  9. data/lib/castle/api/get_device.rb +20 -0
  10. data/lib/castle/api/get_devices_for_user.rb +20 -0
  11. data/lib/castle/api/log.rb +37 -0
  12. data/lib/castle/api/report_device.rb +20 -0
  13. data/lib/castle/api/risk.rb +37 -0
  14. data/lib/castle/api/start_impersonation.rb +24 -0
  15. data/lib/castle/api/track.rb +21 -0
  16. data/lib/castle/client.rb +78 -51
  17. data/lib/castle/{extractors/client_id.rb → client_id/extract.rb} +2 -2
  18. data/lib/castle/commands/approve_device.rb +17 -0
  19. data/lib/castle/commands/authenticate.rb +13 -13
  20. data/lib/castle/commands/end_impersonation.rb +25 -0
  21. data/lib/castle/commands/filter.rb +23 -0
  22. data/lib/castle/commands/get_device.rb +17 -0
  23. data/lib/castle/commands/get_devices_for_user.rb +17 -0
  24. data/lib/castle/commands/log.rb +23 -0
  25. data/lib/castle/commands/report_device.rb +17 -0
  26. data/lib/castle/commands/risk.rb +23 -0
  27. data/lib/castle/commands/start_impersonation.rb +25 -0
  28. data/lib/castle/commands/track.rb +12 -13
  29. data/lib/castle/configuration.rb +57 -32
  30. data/lib/castle/context/{default.rb → get_default.rb} +5 -6
  31. data/lib/castle/context/{merger.rb → merge.rb} +3 -3
  32. data/lib/castle/context/prepare.rb +18 -0
  33. data/lib/castle/context/{sanitizer.rb → sanitize.rb} +1 -1
  34. data/lib/castle/core/get_connection.rb +27 -0
  35. data/lib/castle/{api/response.rb → core/process_response.rb} +8 -3
  36. data/lib/castle/core/process_webhook.rb +25 -0
  37. data/lib/castle/core/send_request.rb +42 -0
  38. data/lib/castle/errors.rb +38 -12
  39. data/lib/castle/failover/prepare_response.rb +18 -0
  40. data/lib/castle/failover/strategy.rb +23 -0
  41. data/lib/castle/headers/extract.rb +47 -0
  42. data/lib/castle/headers/filter.rb +40 -0
  43. data/lib/castle/headers/format.rb +24 -0
  44. data/lib/castle/{extractors/ip.rb → ips/extract.rb} +31 -9
  45. data/lib/castle/logger.rb +19 -0
  46. data/lib/castle/payload/prepare.rb +26 -0
  47. data/lib/castle/secure_mode.rb +7 -2
  48. data/lib/castle/session.rb +18 -0
  49. data/lib/castle/singleton_configuration.rb +9 -0
  50. data/lib/castle/support/hanami.rb +2 -6
  51. data/lib/castle/support/rails.rb +1 -3
  52. data/lib/castle/utils/clean_invalid_chars.rb +22 -0
  53. data/lib/castle/utils/clone.rb +15 -0
  54. data/lib/castle/utils/deep_symbolize_keys.rb +45 -0
  55. data/lib/castle/utils/get_timestamp.rb +15 -0
  56. data/lib/castle/utils/{merger.rb → merge.rb} +3 -3
  57. data/lib/castle/utils/secure_compare.rb +22 -0
  58. data/lib/castle/validators/not_supported.rb +1 -0
  59. data/lib/castle/validators/present.rb +1 -0
  60. data/lib/castle/verdict.rb +15 -0
  61. data/lib/castle/version.rb +1 -1
  62. data/lib/castle/webhooks/verify.rb +45 -0
  63. data/spec/integration/rails/rails_spec.rb +42 -14
  64. data/spec/integration/rails/support/application.rb +3 -1
  65. data/spec/integration/rails/support/home_controller.rb +50 -6
  66. data/spec/lib/castle/api/approve_device_spec.rb +21 -0
  67. data/spec/lib/castle/api/authenticate_spec.rb +136 -0
  68. data/spec/lib/castle/api/end_impersonation_spec.rb +65 -0
  69. data/spec/lib/castle/api/filter_spec.rb +5 -0
  70. data/spec/lib/castle/api/get_device_spec.rb +19 -0
  71. data/spec/lib/castle/api/get_devices_for_user_spec.rb +19 -0
  72. data/spec/lib/castle/api/log_spec.rb +5 -0
  73. data/spec/lib/castle/api/report_device_spec.rb +21 -0
  74. data/spec/lib/castle/api/risk_spec.rb +5 -0
  75. data/spec/lib/castle/api/start_impersonation_spec.rb +65 -0
  76. data/spec/lib/castle/api/track_spec.rb +72 -0
  77. data/spec/lib/castle/api_spec.rb +14 -15
  78. data/spec/lib/castle/{extractors/client_id_spec.rb → client_id/extract_spec.rb} +6 -15
  79. data/spec/lib/castle/client_spec.rb +108 -93
  80. data/spec/lib/castle/commands/approve_device_spec.rb +24 -0
  81. data/spec/lib/castle/commands/authenticate_spec.rb +15 -31
  82. data/spec/lib/castle/commands/end_impersonation_spec.rb +79 -0
  83. data/spec/lib/castle/commands/filter_spec.rb +99 -0
  84. data/spec/lib/castle/commands/get_device_spec.rb +24 -0
  85. data/spec/lib/castle/commands/{review_spec.rb → get_devices_for_user_spec.rb} +7 -7
  86. data/spec/lib/castle/commands/log_spec.rb +100 -0
  87. data/spec/lib/castle/commands/report_device_spec.rb +24 -0
  88. data/spec/lib/castle/commands/risk_spec.rb +100 -0
  89. data/spec/lib/castle/commands/start_impersonation_spec.rb +79 -0
  90. data/spec/lib/castle/commands/track_spec.rb +14 -34
  91. data/spec/lib/castle/configuration_spec.rb +8 -141
  92. data/spec/lib/castle/context/{default_spec.rb → get_default_spec.rb} +9 -10
  93. data/spec/lib/castle/context/{merger_spec.rb → merge_spec.rb} +1 -1
  94. data/spec/lib/castle/context/prepare_spec.rb +43 -0
  95. data/spec/lib/castle/context/{sanitizer_spec.rb → sanitize_spec.rb} +1 -1
  96. data/spec/lib/castle/core/get_connection_spec.rb +43 -0
  97. data/spec/lib/castle/{api/response_spec.rb → core/process_response_spec.rb} +49 -1
  98. data/spec/lib/castle/core/process_webhook_spec.rb +46 -0
  99. data/spec/lib/castle/core/send_request_spec.rb +77 -0
  100. data/spec/lib/castle/failover/strategy_spec.rb +12 -0
  101. data/spec/lib/castle/{extractors/headers_spec.rb → headers/extract_spec.rb} +18 -20
  102. data/spec/lib/castle/headers/filter_spec.rb +39 -0
  103. data/spec/lib/castle/headers/format_spec.rb +25 -0
  104. data/spec/lib/castle/{extractors/ip_spec.rb → ips/extract_spec.rb} +27 -8
  105. data/spec/lib/castle/logger_spec.rb +38 -0
  106. data/spec/lib/castle/payload/prepare_spec.rb +55 -0
  107. data/spec/lib/castle/session_spec.rb +65 -0
  108. data/spec/lib/castle/singleton_configuration_spec.rb +14 -0
  109. data/spec/lib/castle/utils/clean_invalid_chars_spec.rb +69 -0
  110. data/spec/lib/castle/utils/{cloner_spec.rb → clone_spec.rb} +3 -3
  111. data/spec/lib/castle/utils/deep_symbolize_keys_spec.rb +50 -0
  112. data/spec/lib/castle/utils/{timestamp_spec.rb → get_timestamp_spec.rb} +1 -1
  113. data/spec/lib/castle/utils/merge_spec.rb +15 -0
  114. data/spec/lib/castle/validators/present_spec.rb +5 -6
  115. data/spec/lib/castle/verdict_spec.rb +9 -0
  116. data/spec/lib/castle/webhooks/verify_spec.rb +53 -0
  117. data/spec/lib/castle_spec.rb +4 -10
  118. data/spec/spec_helper.rb +3 -3
  119. data/spec/support/shared_examples/action_request.rb +152 -0
  120. data/spec/support/shared_examples/configuration.rb +101 -0
  121. metadata +146 -64
  122. data/lib/castle/api/request.rb +0 -42
  123. data/lib/castle/api/session.rb +0 -39
  124. data/lib/castle/commands/identify.rb +0 -23
  125. data/lib/castle/commands/impersonate.rb +0 -26
  126. data/lib/castle/commands/review.rb +0 -14
  127. data/lib/castle/events.rb +0 -49
  128. data/lib/castle/extractors/headers.rb +0 -45
  129. data/lib/castle/failover_auth_response.rb +0 -21
  130. data/lib/castle/headers_filter.rb +0 -35
  131. data/lib/castle/headers_formatter.rb +0 -22
  132. data/lib/castle/review.rb +0 -11
  133. data/lib/castle/utils.rb +0 -55
  134. data/lib/castle/utils/cloner.rb +0 -11
  135. data/lib/castle/utils/timestamp.rb +0 -12
  136. data/spec/lib/castle/api/request_spec.rb +0 -72
  137. data/spec/lib/castle/commands/identify_spec.rb +0 -88
  138. data/spec/lib/castle/commands/impersonate_spec.rb +0 -107
  139. data/spec/lib/castle/events_spec.rb +0 -5
  140. data/spec/lib/castle/headers_filter_spec.rb +0 -37
  141. data/spec/lib/castle/headers_formatter_spec.rb +0 -25
  142. data/spec/lib/castle/review_spec.rb +0 -19
  143. data/spec/lib/castle/utils/merger_spec.rb +0 -13
  144. data/spec/lib/castle/utils_spec.rb +0 -156
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::API::Track do
4
+ subject(:call) { described_class.call(options) }
5
+
6
+ let(:ip) { '1.2.3.4' }
7
+ let(:cookie_id) { 'abcd' }
8
+ let(:ua) { 'Chrome' }
9
+ let(:env) do
10
+ Rack::MockRequest.env_for(
11
+ '/',
12
+ 'HTTP_USER_AGENT' => ua,
13
+ 'HTTP_X_FORWARDED_FOR' => ip,
14
+ 'HTTP_COOKIE' => "__cid=#{cookie_id};other=efgh"
15
+ )
16
+ end
17
+ let(:request) { Rack::Request.new(env) }
18
+ let(:context) { Castle::Context::Prepare.call(request) }
19
+ let(:time_now) { Time.now }
20
+ let(:time_auto) { time_now.utc.iso8601(3) }
21
+ let(:time_user) { (Time.now - 10_000).utc.iso8601(3) }
22
+ let(:response_body) { {}.to_json }
23
+
24
+ before do
25
+ Timecop.freeze(time_now)
26
+ stub_const('Castle::VERSION', '2.2.0')
27
+ stub_request(:any, /api.castle.io/)
28
+ .with(basic_auth: ['', 'secret'])
29
+ .to_return(status: 200, body: response_body, headers: {})
30
+ end
31
+
32
+ after { Timecop.return }
33
+
34
+ describe 'track' do
35
+ let(:request_body) do
36
+ { event: '$login.succeeded', context: context, user_id: '1234', sent_at: time_auto }
37
+ end
38
+
39
+ before { call }
40
+
41
+ context 'when used with symbol keys' do
42
+ let(:options) { { event: '$login.succeeded', user_id: '1234', context: context } }
43
+
44
+ it do
45
+ assert_requested :post, 'https://api.castle.io/v1/track', times: 1 do |req|
46
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
47
+ end
48
+ end
49
+
50
+ context 'when passed timestamp in options and no defined timestamp' do
51
+ let(:options) do
52
+ { event: '$login.succeeded', user_id: '1234', timestamp: time_user, context: context }
53
+ end
54
+ let(:request_body) do
55
+ {
56
+ event: '$login.succeeded',
57
+ user_id: '1234',
58
+ context: context,
59
+ timestamp: time_user,
60
+ sent_at: time_auto
61
+ }
62
+ end
63
+
64
+ it do
65
+ assert_requested :post, 'https://api.castle.io/v1/track', times: 1 do |req|
66
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -3,35 +3,34 @@
3
3
  describe Castle::API do
4
4
  subject(:call) { described_class.call(command) }
5
5
 
6
- let(:command) { Castle::Commands::Track.new({}).build(event: '$login.succeeded') }
6
+ let(:command) { Castle::Commands::Track.build(event: '$login.succeeded') }
7
7
 
8
8
  context 'when request timeouts' do
9
9
  before { stub_request(:any, /api.castle.io/).to_timeout }
10
10
 
11
- it do
12
- expect do
13
- call
14
- end.to raise_error(Castle::RequestError)
15
- end
11
+ it { expect { call }.to raise_error(Castle::RequestError) }
16
12
  end
17
13
 
18
14
  context 'when non-OK response code' do
19
15
  before { stub_request(:any, /api.castle.io/).to_return(status: 400) }
20
16
 
21
- it do
22
- expect do
23
- call
24
- end.to raise_error(Castle::BadRequestError)
25
- end
17
+ it { expect { call }.to raise_error(Castle::BadRequestError) }
26
18
  end
27
19
 
28
20
  context 'when no api_secret' do
29
21
  before { allow(Castle.config).to receive(:api_secret).and_return('') }
30
22
 
31
- it do
32
- expect do
33
- call
34
- end.to raise_error(Castle::ConfigurationError)
23
+ it { expect { call }.to raise_error(Castle::ConfigurationError) }
24
+ end
25
+
26
+ context 'when custom config' do
27
+ let(:config) { Castle::Configuration.new }
28
+
29
+ before do
30
+ config.api_secret = 'test'
31
+ stub_request(:any, /api.castle.io/)
35
32
  end
33
+
34
+ it { expect { call }.not_to raise_error }
36
35
  end
37
36
  end
@@ -1,16 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Castle::Extractors::ClientId do
3
+ describe Castle::ClientId::Extract do
4
4
  subject(:extractor) { described_class.new(formatted_headers, cookies) }
5
5
 
6
- let(:formatted_headers) { Castle::HeadersFilter.new(request).call }
6
+ let(:formatted_headers) { Castle::Headers::Filter.new(request).call }
7
7
  let(:client_id_cookie) { 'abcd' }
8
8
  let(:client_id_header) { 'abcde' }
9
9
  let(:cookies) { request.cookies }
10
10
  let(:request) { Rack::Request.new(env) }
11
- let(:env) do
12
- Rack::MockRequest.env_for('/', headers)
13
- end
11
+ let(:env) { Rack::MockRequest.env_for('/', headers) }
14
12
 
15
13
  context 'with client_id' do
16
14
  let(:headers) do
@@ -20,17 +18,12 @@ describe Castle::Extractors::ClientId do
20
18
  }
21
19
  end
22
20
 
23
- it do
24
- expect(extractor.call).to eql(client_id_cookie)
25
- end
21
+ it { expect(extractor.call).to eql(client_id_cookie) }
26
22
  end
27
23
 
28
24
  context 'with X-Castle-Client-Id header' do
29
25
  let(:headers) do
30
- {
31
- 'HTTP_X_FORWARDED_FOR' => '1.2.3.4',
32
- 'HTTP_X_CASTLE_CLIENT_ID' => client_id_header
33
- }
26
+ { 'HTTP_X_FORWARDED_FOR' => '1.2.3.4', 'HTTP_X_CASTLE_CLIENT_ID' => client_id_header }
34
27
  end
35
28
 
36
29
  it 'appends the client_id' do
@@ -42,9 +35,7 @@ describe Castle::Extractors::ClientId do
42
35
  let(:cookies) { nil }
43
36
  let(:headers) { {} }
44
37
 
45
- it do
46
- expect(extractor.call).to eql('')
47
- end
38
+ it { expect(extractor.call).to eql('') }
48
39
  end
49
40
 
50
41
  context 'with X-Castle-Client-Id header and cookies client' do
@@ -14,26 +14,26 @@ describe Castle::Client do
14
14
  end
15
15
  let(:request) { Rack::Request.new(env) }
16
16
  let(:client) { described_class.from_request(request) }
17
- let(:request_to_context) { described_class.to_context(request) }
17
+ let(:request_to_context) { Castle::Context::Prepare.call(request) }
18
18
  let(:client_with_user_timestamp) do
19
- described_class.new(request_to_context, timestamp: time_user)
19
+ described_class.new(context: request_to_context, timestamp: time_user)
20
20
  end
21
- let(:client_with_no_timestamp) { described_class.new(request_to_context) }
21
+ let(:client_with_no_timestamp) { described_class.new(context: request_to_context) }
22
22
 
23
23
  let(:headers) do
24
- {
25
- 'Content-Length': '0', 'User-Agent': ua, 'X-Forwarded-For': ip.to_s, 'Cookie': true
26
- }
24
+ { 'Content-Length': '0', 'User-Agent': ua, 'X-Forwarded-For': ip.to_s, 'Cookie': true }
27
25
  end
28
26
  let(:context) do
29
27
  {
30
28
  client_id: 'abcd',
31
29
  active: true,
32
- origin: 'web',
33
30
  user_agent: ua,
34
31
  headers: headers,
35
32
  ip: ip,
36
- library: { name: 'castle-rb', version: '2.2.0' }
33
+ library: {
34
+ name: 'castle-rb',
35
+ version: '2.2.0'
36
+ }
37
37
  }
38
38
  end
39
39
 
@@ -45,53 +45,43 @@ describe Castle::Client do
45
45
  before do
46
46
  Timecop.freeze(time_now)
47
47
  stub_const('Castle::VERSION', '2.2.0')
48
- stub_request(:any, /api.castle.io/).with(
49
- basic_auth: ['', 'secret']
50
- ).to_return(status: 200, body: response_body, headers: {})
48
+ stub_request(:any, /api.castle.io/)
49
+ .with(basic_auth: ['', 'secret'])
50
+ .to_return(status: 200, body: response_body, headers: {})
51
51
  end
52
52
 
53
53
  after { Timecop.return }
54
54
 
55
55
  describe 'parses the request' do
56
- before do
57
- allow(Castle::API).to receive(:request).and_call_original
58
- end
56
+ before { allow(Castle::API).to receive(:send_request).and_call_original }
59
57
 
60
58
  it do
61
59
  client.authenticate(event: '$login.succeeded', user_id: '1234')
62
- expect(Castle::API).to have_received(:request)
63
- end
64
- end
65
-
66
- describe 'to_context' do
67
- it do
68
- expect(described_class.to_context(request)).to eql(context)
60
+ expect(Castle::API).to have_received(:send_request)
69
61
  end
70
62
  end
71
63
 
72
- describe 'to_options' do
73
- let(:options) { { user_id: '1234', user_traits: { name: 'Jo' } } }
74
- let(:result) { { user_id: '1234', user_traits: { name: 'Jo' }, timestamp: time_auto } }
75
-
76
- it do
77
- expect(described_class.to_options(options)).to eql(result)
78
- end
79
- end
80
-
81
- describe 'impersonate' do
64
+ describe 'end impersonation' do
82
65
  let(:impersonator) { 'test@castle.io' }
83
66
  let(:request_body) do
84
- { user_id: '1234', timestamp: time_auto, sent_at: time_auto,
85
- impersonator: impersonator, context: context }
67
+ {
68
+ user_id: '1234',
69
+ timestamp: time_auto,
70
+ sent_at: time_auto,
71
+ properties: {
72
+ impersonator: impersonator
73
+ },
74
+ context: context
75
+ }
86
76
  end
87
77
  let(:response_body) { { success: true }.to_json }
88
- let(:options) { { user_id: '1234', impersonator: impersonator } }
78
+ let(:options) { { user_id: '1234', properties: { impersonator: impersonator } } }
89
79
 
90
80
  context 'when used with symbol keys' do
91
- before { client.impersonate(options) }
81
+ before { client.end_impersonation(options) }
92
82
 
93
83
  it do
94
- assert_requested :post, 'https://api.castle.io/v1/impersonate', times: 1 do |req|
84
+ assert_requested :delete, 'https://api.castle.io/v1/impersonate', times: 1 do |req|
95
85
  JSON.parse(req.body) == JSON.parse(request_body.to_json)
96
86
  end
97
87
  end
@@ -100,64 +90,43 @@ describe Castle::Client do
100
90
  context 'when request is not successful' do
101
91
  let(:response_body) { {}.to_json }
102
92
 
103
- it { expect { client.impersonate(options) }.to raise_error(Castle::ImpersonationFailed) }
93
+ it do
94
+ expect { client.end_impersonation(options) }.to raise_error(Castle::ImpersonationFailed)
95
+ end
104
96
  end
105
97
  end
106
98
 
107
- describe 'identify' do
99
+ describe 'start impersonation' do
100
+ let(:impersonator) { 'test@castle.io' }
108
101
  let(:request_body) do
109
- { user_id: '1234', timestamp: time_auto,
110
- sent_at: time_auto, context: context, user_traits: { name: 'Jo' } }
102
+ {
103
+ user_id: '1234',
104
+ timestamp: time_auto,
105
+ sent_at: time_auto,
106
+ properties: {
107
+ impersonator: impersonator
108
+ },
109
+ context: context
110
+ }
111
111
  end
112
-
113
- before { client.identify(options) }
112
+ let(:response_body) { { success: true }.to_json }
113
+ let(:options) { { user_id: '1234', properties: { impersonator: impersonator } } }
114
114
 
115
115
  context 'when used with symbol keys' do
116
- let(:options) { { user_id: '1234', user_traits: { name: 'Jo' } } }
116
+ before { client.start_impersonation(options) }
117
117
 
118
118
  it do
119
- assert_requested :post, 'https://api.castle.io/v1/identify', times: 1 do |req|
119
+ assert_requested :post, 'https://api.castle.io/v1/impersonate', times: 1 do |req|
120
120
  JSON.parse(req.body) == JSON.parse(request_body.to_json)
121
121
  end
122
122
  end
123
-
124
- context 'when passed timestamp in options and no defined timestamp' do
125
- let(:client) { client_with_no_timestamp }
126
- let(:options) { { user_id: '1234', user_traits: { name: 'Jo' }, timestamp: time_user } }
127
- let(:request_body) do
128
- { user_id: '1234', user_traits: { name: 'Jo' }, context: context,
129
- timestamp: time_user, sent_at: time_auto }
130
- end
131
-
132
- it do
133
- assert_requested :post, 'https://api.castle.io/v1/identify', times: 1 do |req|
134
- JSON.parse(req.body) == JSON.parse(request_body.to_json)
135
- end
136
- end
137
- end
138
-
139
- context 'with client initialized with timestamp' do
140
- let(:client) { client_with_user_timestamp }
141
- let(:request_body) do
142
- { user_id: '1234', timestamp: time_user, sent_at: time_auto,
143
- context: context, user_traits: { name: 'Jo' } }
144
- end
145
-
146
- it do
147
- assert_requested :post, 'https://api.castle.io/v1/identify', times: 1 do |req|
148
- JSON.parse(req.body) == JSON.parse(request_body.to_json)
149
- end
150
- end
151
- end
152
123
  end
153
124
 
154
- context 'when used with string keys' do
155
- let(:options) { { 'user_id' => '1234', 'user_traits' => { 'name' => 'Jo' } } }
125
+ context 'when request is not successful' do
126
+ let(:response_body) { {}.to_json }
156
127
 
157
128
  it do
158
- assert_requested :post, 'https://api.castle.io/v1/identify', times: 1 do |req|
159
- JSON.parse(req.body) == JSON.parse(request_body.to_json)
160
- end
129
+ expect { client.start_impersonation(options) }.to raise_error(Castle::ImpersonationFailed)
161
130
  end
162
131
  end
163
132
  end
@@ -166,8 +135,13 @@ describe Castle::Client do
166
135
  let(:options) { { event: '$login.succeeded', user_id: '1234' } }
167
136
  let(:request_response) { client.authenticate(options) }
168
137
  let(:request_body) do
169
- { event: '$login.succeeded', user_id: '1234', context: context,
170
- timestamp: time_auto, sent_at: time_auto }
138
+ {
139
+ event: '$login.succeeded',
140
+ user_id: '1234',
141
+ context: context,
142
+ timestamp: time_auto,
143
+ sent_at: time_auto
144
+ }
171
145
  end
172
146
 
173
147
  context 'when used with symbol keys' do
@@ -183,8 +157,13 @@ describe Castle::Client do
183
157
  let(:client) { client_with_no_timestamp }
184
158
  let(:options) { { event: '$login.succeeded', user_id: '1234', timestamp: time_user } }
185
159
  let(:request_body) do
186
- { event: '$login.succeeded', user_id: '1234', context: context,
187
- timestamp: time_user, sent_at: time_auto }
160
+ {
161
+ event: '$login.succeeded',
162
+ user_id: '1234',
163
+ context: context,
164
+ timestamp: time_user,
165
+ sent_at: time_auto
166
+ }
188
167
  end
189
168
 
190
169
  it do
@@ -197,8 +176,13 @@ describe Castle::Client do
197
176
  context 'with client initialized with timestamp' do
198
177
  let(:client) { client_with_user_timestamp }
199
178
  let(:request_body) do
200
- { event: '$login.succeeded', user_id: '1234', context: context,
201
- timestamp: time_user, sent_at: time_auto }
179
+ {
180
+ event: '$login.succeeded',
181
+ user_id: '1234',
182
+ context: context,
183
+ timestamp: time_user,
184
+ sent_at: time_auto
185
+ }
202
186
  end
203
187
 
204
188
  it do
@@ -241,7 +225,7 @@ describe Castle::Client do
241
225
  end
242
226
 
243
227
  it { assert_not_requested :post, 'https://api.castle.io/v1/authenticate' }
244
- it { expect(request_response[:action]).to be_eql('allow') }
228
+ it { expect(request_response[:action]).to be_eql(Castle::Verdict::ALLOW) }
245
229
  it { expect(request_response[:user_id]).to be_eql('1234') }
246
230
  it { expect(request_response[:failover]).to be true }
247
231
  it { expect(request_response[:failover_reason]).to be_eql('Castle is set to do not track.') }
@@ -249,7 +233,9 @@ describe Castle::Client do
249
233
 
250
234
  context 'when request with fail' do
251
235
  before do
252
- allow(Castle::API).to receive(:request).and_raise(Castle::RequestError.new(Timeout::Error))
236
+ allow(Castle::API).to receive(:send_request).and_raise(
237
+ Castle::RequestError.new(Timeout::Error)
238
+ )
253
239
  end
254
240
 
255
241
  context 'with request error and throw strategy' do
@@ -268,7 +254,9 @@ describe Castle::Client do
268
254
  end
269
255
 
270
256
  context 'when request is internal server error' do
271
- before { allow(Castle::API).to receive(:request).and_raise(Castle::InternalServerError) }
257
+ before do
258
+ allow(Castle::API).to receive(:send_request).and_raise(Castle::InternalServerError)
259
+ end
272
260
 
273
261
  describe 'throw strategy' do
274
262
  before { allow(Castle.config).to receive(:failover_strategy).and_return(:throw) }
@@ -288,8 +276,13 @@ describe Castle::Client do
288
276
 
289
277
  describe 'track' do
290
278
  let(:request_body) do
291
- { event: '$login.succeeded', context: context, user_id: '1234',
292
- timestamp: time_auto, sent_at: time_auto }
279
+ {
280
+ event: '$login.succeeded',
281
+ context: context,
282
+ user_id: '1234',
283
+ timestamp: time_auto,
284
+ sent_at: time_auto
285
+ }
293
286
  end
294
287
 
295
288
  before { client.track(options) }
@@ -307,8 +300,13 @@ describe Castle::Client do
307
300
  let(:client) { client_with_no_timestamp }
308
301
  let(:options) { { event: '$login.succeeded', user_id: '1234', timestamp: time_user } }
309
302
  let(:request_body) do
310
- { event: '$login.succeeded', user_id: '1234', context: context,
311
- timestamp: time_user, sent_at: time_auto }
303
+ {
304
+ event: '$login.succeeded',
305
+ user_id: '1234',
306
+ context: context,
307
+ timestamp: time_user,
308
+ sent_at: time_auto
309
+ }
312
310
  end
313
311
 
314
312
  it do
@@ -321,8 +319,13 @@ describe Castle::Client do
321
319
  context 'with client initialized with timestamp' do
322
320
  let(:client) { client_with_user_timestamp }
323
321
  let(:request_body) do
324
- { event: '$login.succeeded', context: context, user_id: '1234',
325
- timestamp: time_user, sent_at: time_auto }
322
+ {
323
+ event: '$login.succeeded',
324
+ context: context,
325
+ user_id: '1234',
326
+ timestamp: time_user,
327
+ sent_at: time_auto
328
+ }
326
329
  end
327
330
 
328
331
  it do
@@ -357,4 +360,16 @@ describe Castle::Client do
357
360
  it { expect(client).to be_tracked }
358
361
  end
359
362
  end
363
+
364
+ describe 'filter' do
365
+ it_behaves_like 'action request', :filter
366
+ end
367
+
368
+ describe 'risk' do
369
+ it_behaves_like 'action request', :risk
370
+ end
371
+
372
+ describe 'log' do
373
+ it_behaves_like 'action request', :log
374
+ end
360
375
  end