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
@@ -1,17 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Castle::Context::Default do
3
+ describe Castle::Context::GetDefault do
4
4
  subject { described_class.new(request, nil) }
5
5
 
6
6
  let(:ip) { '1.2.3.4' }
7
7
  let(:client_id) { 'abcd' }
8
8
 
9
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=#{client_id};other=efgh")
10
+ Rack::MockRequest.env_for(
11
+ '/',
12
+ 'HTTP_X_FORWARDED_FOR' => ip,
13
+ 'HTTP_ACCEPT_LANGUAGE' => 'en',
14
+ 'HTTP_USER_AGENT' => 'test',
15
+ 'HTTP_COOKIE' => "__cid=#{client_id};other=efgh"
16
+ )
15
17
  end
16
18
  let(:request) { Rack::Request.new(env) }
17
19
  let(:default_context) { subject.call }
@@ -26,12 +28,9 @@ describe Castle::Context::Default do
26
28
  }
27
29
  end
28
30
 
29
- before do
30
- stub_const('Castle::VERSION', version)
31
- end
31
+ before { stub_const('Castle::VERSION', version) }
32
32
 
33
33
  it { expect(default_context[:active]).to be_eql(true) }
34
- it { expect(default_context[:origin]).to be_eql('web') }
35
34
  it { expect(default_context[:headers]).to be_eql(result_headers) }
36
35
  it { expect(default_context[:ip]).to be_eql(ip) }
37
36
  it { expect(default_context[:client_id]).to be_eql(client_id) }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Castle::Context::Merger do
3
+ describe Castle::Context::Merge do
4
4
  let(:first) { { test: { test1: { c: '4' } } } }
5
5
 
6
6
  describe '#call' do
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Context::Prepare do
4
+ let(:ip) { '1.2.3.4' }
5
+ let(:cookie_id) { 'abcd' }
6
+ let(:ua) { 'Chrome' }
7
+ let(:env) do
8
+ Rack::MockRequest.env_for(
9
+ '/',
10
+ 'HTTP_USER_AGENT' => ua,
11
+ 'HTTP_X_FORWARDED_FOR' => ip,
12
+ 'HTTP_COOKIE' => "__cid=#{cookie_id};other=efgh"
13
+ )
14
+ end
15
+ let(:request) { Rack::Request.new(env) }
16
+ let(:context) do
17
+ {
18
+ client_id: 'abcd',
19
+ active: true,
20
+ user_agent: ua,
21
+ headers: headers,
22
+ ip: ip,
23
+ library: {
24
+ name: 'castle-rb',
25
+ version: '6.0.0'
26
+ }
27
+ }
28
+ end
29
+
30
+ let(:headers) do
31
+ { 'Content-Length': '0', 'User-Agent': ua, 'X-Forwarded-For': ip.to_s, 'Cookie': true }
32
+ end
33
+
34
+ before { stub_const('Castle::VERSION', '6.0.0') }
35
+
36
+ describe '#call' do
37
+ subject(:generated) { described_class.call(request) }
38
+
39
+ context 'when active true' do
40
+ it { is_expected.to eql(context) }
41
+ end
42
+ end
43
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Castle::Context::Sanitizer do
3
+ describe Castle::Context::Sanitize do
4
4
  let(:paylod) { { test: 'test' } }
5
5
 
6
6
  describe '#call' do
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Core::GetConnection do
4
+ describe '.call' do
5
+ subject(:class_call) { described_class.call }
6
+
7
+ context 'when ssl false' do
8
+ let(:localhost) { 'localhost' }
9
+ let(:port) { 3002 }
10
+ let(:api_url) { '/test' }
11
+
12
+ before do
13
+ Castle.config.base_url = 'http://localhost:3002'
14
+
15
+ allow(Net::HTTP).to receive(:new).with(localhost, port).and_call_original
16
+ end
17
+
18
+ it do
19
+ class_call
20
+
21
+ expect(Net::HTTP).to have_received(:new).with(localhost, port)
22
+ end
23
+
24
+ it { expect(class_call).to be_an_instance_of(Net::HTTP) }
25
+ end
26
+
27
+ context 'when ssl true' do
28
+ let(:localhost) { 'localhost' }
29
+ let(:port) { 443 }
30
+
31
+ before { Castle.config.base_url = 'https://localhost' }
32
+
33
+ context 'with block' do
34
+ let(:api_url) { '/test' }
35
+ let(:request) { Net::HTTP::Get.new(api_url) }
36
+
37
+ before { allow(Net::HTTP).to receive(:new).with(localhost, port).and_call_original }
38
+
39
+ it { expect(class_call).to be_an_instance_of(Net::HTTP) }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Castle::API::Response do
3
+ describe Castle::Core::ProcessResponse do
4
4
  describe '#call' do
5
5
  subject(:call) { described_class.call(response) }
6
6
 
@@ -10,6 +10,54 @@ describe Castle::API::Response do
10
10
  it { expect(call).to eql(user: 1) }
11
11
  end
12
12
 
13
+ describe 'authenticate' do
14
+ context 'when allow without any additional props' do
15
+ let(:response) { OpenStruct.new(body: '{"action":"allow","user_id":"12345"}', code: 200) }
16
+
17
+ it { expect(call).to eql({ action: 'allow', user_id: '12345' }) }
18
+ end
19
+
20
+ context 'when allow with additional props' do
21
+ let(:response) do
22
+ OpenStruct.new(body: '{"action":"allow","user_id":"12345","internal":{}}', code: 200)
23
+ end
24
+
25
+ it { expect(call).to eql({ action: 'allow', user_id: '12345', internal: {} }) }
26
+ end
27
+
28
+ context 'when deny without risk policy' do
29
+ let(:response) do
30
+ OpenStruct.new(body: '{"action":"deny","user_id":"1","device_token":"abc"}', code: 200)
31
+ end
32
+
33
+ it { expect(call).to eql({ action: 'deny', user_id: '1', device_token: 'abc' }) }
34
+ end
35
+
36
+ context 'when deny with risk policy' do
37
+ let(:body) do
38
+ '{"action":"deny","user_id":"1","device_token":"abc",
39
+ "risk_policy":{"id":"123","revision_id":"abc","name":"def","type":"bot"}}'
40
+ end
41
+ let(:response) { OpenStruct.new({ body: body, code: 200 }) }
42
+
43
+ let(:result) do
44
+ {
45
+ action: 'deny',
46
+ user_id: '1',
47
+ device_token: 'abc',
48
+ risk_policy: {
49
+ id: '123',
50
+ revision_id: 'abc',
51
+ name: 'def',
52
+ type: 'bot'
53
+ }
54
+ }
55
+ end
56
+
57
+ it { expect(call).to eql(result) }
58
+ end
59
+ end
60
+
13
61
  context 'when response empty' do
14
62
  let(:response) { OpenStruct.new(body: '', code: 200) }
15
63
 
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Core::ProcessWebhook do
4
+ describe '#call' do
5
+ subject(:call) { described_class.call(webhook) }
6
+
7
+ let(:webhook_body) do
8
+ {
9
+ api_version: 'v1',
10
+ app_id: '12345',
11
+ type: '$incident.confirmed',
12
+ created_at: '2020-12-18T12:55:21.779Z',
13
+ data: {
14
+ id: 'test',
15
+ device_token: 'token',
16
+ user_id: '',
17
+ trigger: '$login.succeeded',
18
+ context: {},
19
+ location: {},
20
+ user_agent: {}
21
+ },
22
+ user_traits: {},
23
+ properties: {},
24
+ policy: {}
25
+ }.to_json
26
+ end
27
+
28
+ let(:webhook) { OpenStruct.new(body: StringIO.new(webhook_body)) }
29
+
30
+ context 'when success' do
31
+ it { expect(call).to eql(webhook_body) }
32
+ end
33
+
34
+ context 'when webhook empty' do
35
+ let(:webhook) { OpenStruct.new(body: StringIO.new('')) }
36
+
37
+ it { expect { call }.to raise_error(Castle::ApiError, 'Invalid webhook from Castle API') }
38
+ end
39
+
40
+ context 'when webhook nil' do
41
+ let(:webhook) { OpenStruct.new(body: StringIO.new) }
42
+
43
+ it { expect { call }.to raise_error(Castle::ApiError, 'Invalid webhook from Castle API') }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Core::SendRequest do
4
+ let(:config) { Castle.config }
5
+
6
+ describe '#call' do
7
+ let(:command) { Castle::Commands::Track.build(event: '$login.succeeded') }
8
+ let(:headers) { {} }
9
+ let(:request_build) { {} }
10
+ let(:expected_headers) { { 'Content-Type' => 'application/json' } }
11
+ let(:http) { instance_double('Net::HTTP') }
12
+
13
+ context 'without http arg provided' do
14
+ subject(:call) { described_class.call(command, headers, nil, config) }
15
+
16
+ let(:http) { instance_double('Net::HTTP') }
17
+ let(:command) { Castle::Commands::Track.build(event: '$login.succeeded') }
18
+ let(:headers) { {} }
19
+ let(:request_build) { {} }
20
+ let(:expected_headers) { { 'Content-Type' => 'application/json' } }
21
+
22
+ before do
23
+ allow(Castle::Core::GetConnection).to receive(:call).and_return(http)
24
+ allow(http).to receive(:request)
25
+ allow(described_class).to receive(:build).and_return(request_build)
26
+ call
27
+ end
28
+
29
+ it do
30
+ expect(described_class).to have_received(:build).with(command, expected_headers, config)
31
+ end
32
+
33
+ it { expect(http).to have_received(:request).with(request_build) }
34
+ end
35
+
36
+ context 'with http arg provided' do
37
+ subject(:call) { described_class.call(command, headers, http, config) }
38
+
39
+ before do
40
+ allow(Castle::Core::GetConnection).to receive(:call)
41
+ allow(http).to receive(:request)
42
+ allow(described_class).to receive(:build).and_return(request_build)
43
+ call
44
+ end
45
+
46
+ it { expect(Castle::Core::GetConnection).not_to have_received(:call) }
47
+
48
+ it do
49
+ expect(described_class).to have_received(:build).with(command, expected_headers, config)
50
+ end
51
+
52
+ it { expect(http).to have_received(:request).with(request_build) }
53
+ end
54
+ end
55
+
56
+ describe '#build' do
57
+ subject(:build) { described_class.build(command, headers, config) }
58
+
59
+ let(:headers) { { 'SAMPLE-HEADER' => '1' } }
60
+ let(:api_secret) { 'secret' }
61
+
62
+ context 'when post' do
63
+ let(:time) { Time.now.utc.iso8601(3) }
64
+ let(:command) { Castle::Commands::Track.build(event: '$login.succeeded', name: "\xC4") }
65
+ let(:expected_body) { { event: '$login.succeeded', name: '�', context: {}, sent_at: time } }
66
+
67
+ before { allow(Castle::Utils::GetTimestamp).to receive(:call).and_return(time) }
68
+
69
+ it { expect(build.body).to be_eql(expected_body.to_json) }
70
+ it { expect(build.method).to eql('POST') }
71
+ it { expect(build.path).to eql("/v1/#{command.path}") }
72
+ it { expect(build.to_hash).to have_key('authorization') }
73
+ it { expect(build.to_hash).to have_key('sample-header') }
74
+ it { expect(build.to_hash['sample-header']).to eql(['1']) }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Failover::Strategy do
4
+ subject(:strategy) { described_class }
5
+
6
+ it { expect(strategy::ALLOW).to be_eql(:allow) }
7
+ it { expect(strategy::DENY).to be_eql(:deny) }
8
+ it { expect(strategy::CHALLENGE).to be_eql(:challenge) }
9
+ it { expect(strategy::THROW).to be_eql(:throw) }
10
+
11
+ it { expect(Castle::Failover::STRATEGIES).to be_eql(%i[allow deny challenge throw]) }
12
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Castle::Extractors::Headers do
4
- subject(:headers) { described_class.new(formatted_headers).call }
3
+ describe Castle::Headers::Extract do
4
+ subject(:extract_call) { described_class.new(formatted_headers).call }
5
5
 
6
6
  let(:formatted_headers) do
7
7
  {
@@ -16,11 +16,11 @@ describe Castle::Extractors::Headers do
16
16
  end
17
17
 
18
18
  after do
19
- Castle.config.whitelisted = %w[]
20
- Castle.config.blacklisted = %w[]
19
+ Castle.config.allowlisted = %w[]
20
+ Castle.config.denylisted = %w[]
21
21
  end
22
22
 
23
- context 'when whitelist is not set in the configuration' do
23
+ context 'when allowlist is not set in the configuration' do
24
24
  let(:result) do
25
25
  {
26
26
  'Accept' => 'application/json',
@@ -33,11 +33,11 @@ describe Castle::Extractors::Headers do
33
33
  }
34
34
  end
35
35
 
36
- it { expect(headers).to eq(result) }
36
+ it { expect(extract_call).to eq(result) }
37
37
  end
38
38
 
39
- context 'when whitelist is set in the configuration' do
40
- before { Castle.config.whitelisted = %w[Accept OK] }
39
+ context 'when allowlist is set in the configuration' do
40
+ before { Castle.config.allowlisted = %w[Accept OK] }
41
41
 
42
42
  let(:result) do
43
43
  {
@@ -51,10 +51,10 @@ describe Castle::Extractors::Headers do
51
51
  }
52
52
  end
53
53
 
54
- it { expect(headers).to eq(result) }
54
+ it { expect(extract_call).to eq(result) }
55
55
  end
56
56
 
57
- context 'when blacklist is set in the configuration' do
57
+ context 'when denylist is set in the configuration' do
58
58
  context 'with a User-Agent' do
59
59
  let(:result) do
60
60
  {
@@ -68,9 +68,9 @@ describe Castle::Extractors::Headers do
68
68
  }
69
69
  end
70
70
 
71
- before { Castle.config.blacklisted = %w[User-Agent] }
71
+ before { Castle.config.denylisted = %w[User-Agent] }
72
72
 
73
- it { expect(headers).to eq(result) }
73
+ it { expect(extract_call).to eq(result) }
74
74
  end
75
75
 
76
76
  context 'with a different header' do
@@ -86,20 +86,18 @@ describe Castle::Extractors::Headers do
86
86
  }
87
87
  end
88
88
 
89
- before { Castle.config.blacklisted = %w[Accept] }
89
+ before { Castle.config.denylisted = %w[Accept] }
90
90
 
91
- it { expect(headers).to eq(result) }
91
+ it { expect(extract_call).to eq(result) }
92
92
  end
93
93
  end
94
94
 
95
- context 'when a header is both whitelisted and blacklisted' do
95
+ context 'when a header is both allowlisted and denylisted' do
96
96
  before do
97
- Castle.config.whitelisted = %w[Accept]
98
- Castle.config.blacklisted = %w[Accept]
97
+ Castle.config.allowlisted = %w[Accept]
98
+ Castle.config.denylisted = %w[Accept]
99
99
  end
100
100
 
101
- it do
102
- expect(headers['Accept']).to eq(true)
103
- end
101
+ it { expect(extract_call['Accept']).to eq(true) }
104
102
  end
105
103
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Headers::Filter do
4
+ subject(:filter_call) { described_class.new(request).call }
5
+
6
+ let(:env) do
7
+ result =
8
+ Rack::MockRequest.env_for(
9
+ '/',
10
+ 'Action-Dispatch.request.content-Type' => 'application/json',
11
+ 'HTTP_AUTHORIZATION' => 'Basic 123456',
12
+ 'HTTP_COOKIE' => '__cid=abcd;other=efgh',
13
+ 'HTTP_ACCEPT' => 'application/json',
14
+ 'HTTP_X_FORWARDED_FOR' => '1.2.3.4',
15
+ 'HTTP_USER_AGENT' => 'Mozilla 1234',
16
+ 'TEST' => '1',
17
+ 'REMOTE_ADDR' => '1.2.3.4'
18
+ )
19
+ result[:HTTP_OK] = 'OK'
20
+ result
21
+ end
22
+ let(:filtered) do
23
+ {
24
+ 'Accept' => 'application/json',
25
+ 'Authorization' => 'Basic 123456',
26
+ 'Cookie' => '__cid=abcd;other=efgh',
27
+ 'Content-Length' => '0',
28
+ 'Ok' => 'OK',
29
+ 'User-Agent' => 'Mozilla 1234',
30
+ 'Remote-Addr' => '1.2.3.4',
31
+ 'X-Forwarded-For' => '1.2.3.4'
32
+ }
33
+ end
34
+ let(:request) { Rack::Request.new(env) }
35
+
36
+ context 'with list of header' do
37
+ it { expect(filter_call).to eq(filtered) }
38
+ end
39
+ end