castle-rb 5.0.0 → 7.1.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 (144) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +113 -39
  3. data/lib/castle.rb +49 -29
  4. data/lib/castle/api.rb +20 -16
  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 +74 -68
  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 +22 -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 +22 -0
  25. data/lib/castle/commands/report_device.rb +17 -0
  26. data/lib/castle/commands/risk.rb +22 -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 +31 -23
  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 +28 -0
  40. data/lib/castle/failover/strategy.rb +23 -0
  41. data/lib/castle/{extractors/headers.rb → headers/extract.rb} +8 -6
  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} +11 -7
  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 +110 -92
  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 +72 -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 +73 -0
  87. data/spec/lib/castle/commands/report_device_spec.rb +24 -0
  88. data/spec/lib/castle/commands/risk_spec.rb +73 -0
  89. data/spec/lib/castle/commands/{impersonate_spec.rb → start_impersonation_spec.rb} +13 -41
  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/{api/request_spec.rb → core/send_request_spec.rb} +16 -37
  100. data/spec/lib/castle/failover/strategy_spec.rb +12 -0
  101. data/spec/lib/castle/{extractors/headers_spec.rb → headers/extract_spec.rb} +7 -9
  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} +5 -14
  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 +155 -0
  120. data/spec/support/shared_examples/configuration.rb +101 -0
  121. metadata +144 -67
  122. data/lib/castle/api/connection.rb +0 -24
  123. data/lib/castle/api/request.rb +0 -42
  124. data/lib/castle/api/session.rb +0 -20
  125. data/lib/castle/commands/identify.rb +0 -23
  126. data/lib/castle/commands/impersonate.rb +0 -26
  127. data/lib/castle/commands/review.rb +0 -14
  128. data/lib/castle/events.rb +0 -49
  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/connection_spec.rb +0 -59
  137. data/spec/lib/castle/api/session_spec.rb +0 -86
  138. data/spec/lib/castle/commands/identify_spec.rb +0 -88
  139. data/spec/lib/castle/events_spec.rb +0 -5
  140. data/spec/lib/castle/headers_filter_spec.rb +0 -38
  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,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Castle::Commands::Impersonate do
4
- subject(:instance) { described_class.new(context) }
3
+ describe Castle::Commands::StartImpersonation do
4
+ subject(:instance) { described_class }
5
5
 
6
6
  let(:context) { { user_agent: 'test', ip: '127.0.0.1', client_id: 'test' } }
7
7
  let(:impersonator) { 'test@castle.io' }
8
- let(:default_payload) { { user_id: '1234', sent_at: time_auto } }
8
+ let(:default_payload) { { user_id: '1234', sent_at: time_auto, context: context } }
9
9
 
10
10
  let(:time_now) { Time.now }
11
11
  let(:time_auto) { time_now.utc.iso8601(3) }
@@ -17,24 +17,6 @@ describe Castle::Commands::Impersonate do
17
17
  describe '.build' do
18
18
  subject(:command) { instance.build(payload) }
19
19
 
20
- context 'with simple merger' do
21
- let(:payload) { default_payload.merge(context: { test: { test2: '1' } }) }
22
- let(:command_data) do
23
- default_payload.merge(
24
- context: {
25
- test: { test2: '1' },
26
- user_agent: 'test',
27
- ip: '127.0.0.1',
28
- client_id: 'test'
29
- }
30
- )
31
- end
32
-
33
- it { expect(command.method).to be_eql(:post) }
34
- it { expect(command.path).to be_eql('impersonate') }
35
- it { expect(command.data).to be_eql(command_data) }
36
- end
37
-
38
20
  context 'with impersonator' do
39
21
  let(:payload) { default_payload.merge(properties: { impersonator: impersonator }) }
40
22
  let(:command_data) do
@@ -47,10 +29,8 @@ describe Castle::Commands::Impersonate do
47
29
  end
48
30
 
49
31
  context 'when active true' do
50
- let(:payload) { default_payload.merge(context: { active: true }) }
51
- let(:command_data) do
52
- default_payload.merge(context: context.merge(active: true))
53
- end
32
+ let(:payload) { default_payload.merge(context: context.merge(active: true)) }
33
+ let(:command_data) { default_payload.merge(context: context.merge(active: true)) }
54
34
 
55
35
  it { expect(command.method).to be_eql(:post) }
56
36
  it { expect(command.path).to be_eql('impersonate') }
@@ -58,10 +38,8 @@ describe Castle::Commands::Impersonate do
58
38
  end
59
39
 
60
40
  context 'when active false' do
61
- let(:payload) { default_payload.merge(context: { active: false }) }
62
- let(:command_data) do
63
- default_payload.merge(context: context.merge(active: false))
64
- end
41
+ let(:payload) { default_payload.merge(context: context.merge(active: false)) }
42
+ let(:command_data) { default_payload.merge(context: context.merge(active: false)) }
65
43
 
66
44
  it { expect(command.method).to be_eql(:post) }
67
45
  it { expect(command.path).to be_eql('impersonate') }
@@ -69,20 +47,13 @@ describe Castle::Commands::Impersonate do
69
47
  end
70
48
 
71
49
  context 'when active string' do
72
- let(:payload) { default_payload.merge(context: { active: 'string' }) }
50
+ let(:payload) { default_payload.merge(context: context.merge(active: 'string')) }
73
51
  let(:command_data) { default_payload.merge(context: context) }
74
52
 
75
53
  it { expect(command.method).to be_eql(:post) }
76
54
  it { expect(command.path).to be_eql('impersonate') }
77
55
  it { expect(command.data).to be_eql(command_data) }
78
56
  end
79
-
80
- context 'when reset' do
81
- let(:payload) { default_payload.merge(reset: true) }
82
-
83
- it { expect(command.method).to be_eql(:delete) }
84
- it { expect(command.path).to be_eql('impersonate') }
85
- end
86
57
  end
87
58
 
88
59
  describe '#validate!' do
@@ -92,14 +63,15 @@ describe Castle::Commands::Impersonate do
92
63
  let(:payload) { {} }
93
64
 
94
65
  it do
95
- expect do
96
- validate!
97
- end.to raise_error(Castle::InvalidParametersError, 'user_id is missing or empty')
66
+ expect { validate! }.to raise_error(
67
+ Castle::InvalidParametersError,
68
+ 'user_id is missing or empty'
69
+ )
98
70
  end
99
71
  end
100
72
 
101
73
  context 'when user_id present' do
102
- let(:payload) { { user_id: '1234' } }
74
+ let(:payload) { { user_id: '1234', context: context } }
103
75
 
104
76
  it { expect { validate! }.not_to raise_error }
105
77
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe Castle::Commands::Track do
4
- subject(:instance) { described_class.new(context) }
4
+ subject(:instance) { described_class }
5
5
 
6
6
  let(:context) { { test: { test1: '1' } } }
7
- let(:default_payload) { { event: '$login.track', sent_at: time_auto } }
7
+ let(:default_payload) { { event: '$login.track', sent_at: time_auto, context: context } }
8
8
 
9
9
  let(:time_now) { Time.now }
10
10
  let(:time_auto) { time_now.utc.iso8601(3) }
@@ -16,22 +16,9 @@ describe Castle::Commands::Track do
16
16
  describe '#build' do
17
17
  subject(:command) { instance.build(payload) }
18
18
 
19
- context 'with simple merger' do
20
- let(:payload) { default_payload.merge(context: { test: { test2: '1' } }) }
21
- let(:command_data) do
22
- default_payload.merge(context: { test: { test1: '1', test2: '1' } })
23
- end
24
-
25
- it { expect(command.method).to be_eql(:post) }
26
- it { expect(command.path).to be_eql('track') }
27
- it { expect(command.data).to be_eql(command_data) }
28
- end
29
-
30
19
  context 'with user_id' do
31
20
  let(:payload) { default_payload.merge(user_id: '1234') }
32
- let(:command_data) do
33
- default_payload.merge(user_id: '1234', context: context)
34
- end
21
+ let(:command_data) { default_payload.merge(user_id: '1234', context: context) }
35
22
 
36
23
  it { expect(command.method).to be_eql(:post) }
37
24
  it { expect(command.path).to be_eql('track') }
@@ -40,9 +27,7 @@ describe Castle::Commands::Track do
40
27
 
41
28
  context 'with properties' do
42
29
  let(:payload) { default_payload.merge(properties: { test: '1' }) }
43
- let(:command_data) do
44
- default_payload.merge(properties: { test: '1' }, context: context)
45
- end
30
+ let(:command_data) { default_payload.merge(properties: { test: '1' }, context: context) }
46
31
 
47
32
  it { expect(command.method).to be_eql(:post) }
48
33
  it { expect(command.path).to be_eql('track') }
@@ -51,9 +36,7 @@ describe Castle::Commands::Track do
51
36
 
52
37
  context 'with user_traits' do
53
38
  let(:payload) { default_payload.merge(user_traits: { test: '1' }) }
54
- let(:command_data) do
55
- default_payload.merge(user_traits: { test: '1' }, context: context)
56
- end
39
+ let(:command_data) { default_payload.merge(user_traits: { test: '1' }, context: context) }
57
40
 
58
41
  it { expect(command.method).to be_eql(:post) }
59
42
  it { expect(command.path).to be_eql('track') }
@@ -61,10 +44,8 @@ describe Castle::Commands::Track do
61
44
  end
62
45
 
63
46
  context 'when active true' do
64
- let(:payload) { default_payload.merge(context: { active: true }) }
65
- let(:command_data) do
66
- default_payload.merge(context: context.merge(active: true))
67
- end
47
+ let(:payload) { default_payload.merge(context: context.merge(active: true)) }
48
+ let(:command_data) { default_payload.merge(context: context.merge(active: true)) }
68
49
 
69
50
  it { expect(command.method).to be_eql(:post) }
70
51
  it { expect(command.path).to be_eql('track') }
@@ -72,10 +53,8 @@ describe Castle::Commands::Track do
72
53
  end
73
54
 
74
55
  context 'when active false' do
75
- let(:payload) { default_payload.merge(context: { active: false }) }
76
- let(:command_data) do
77
- default_payload.merge(context: context.merge(active: false))
78
- end
56
+ let(:payload) { default_payload.merge(context: context.merge(active: false)) }
57
+ let(:command_data) { default_payload.merge(context: context.merge(active: false)) }
79
58
 
80
59
  it { expect(command.method).to be_eql(:post) }
81
60
  it { expect(command.path).to be_eql('track') }
@@ -83,7 +62,7 @@ describe Castle::Commands::Track do
83
62
  end
84
63
 
85
64
  context 'when active string' do
86
- let(:payload) { default_payload.merge(context: { active: 'string' }) }
65
+ let(:payload) { default_payload.merge(context: context.merge(active: 'string')) }
87
66
  let(:command_data) { default_payload.merge(context: context) }
88
67
 
89
68
  it { expect(command.method).to be_eql(:post) }
@@ -99,9 +78,10 @@ describe Castle::Commands::Track do
99
78
  let(:payload) { {} }
100
79
 
101
80
  it do
102
- expect do
103
- validate!
104
- end.to raise_error(Castle::InvalidParametersError, 'event is missing or empty')
81
+ expect { validate! }.to raise_error(
82
+ Castle::InvalidParametersError,
83
+ 'event is missing or empty'
84
+ )
105
85
  end
106
86
  end
107
87
 
@@ -1,147 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe Castle::Configuration do
4
- subject(:config) do
5
- described_class.instance
6
- end
4
+ subject(:config) { described_class.new }
7
5
 
8
- describe 'host' do
9
- context 'with default' do
10
- it { expect(config.url.host).to be_eql('api.castle.io') }
11
- end
6
+ it_behaves_like 'configuration_host'
7
+ it_behaves_like 'configuration_request_timeout'
8
+ it_behaves_like 'configuration_allowlisted'
9
+ it_behaves_like 'configuration_denylisted'
10
+ it_behaves_like 'configuration_failover_strategy'
11
+ it_behaves_like 'configuration_api_secret'
12
12
 
13
- context 'with setter' do
14
- before { config.url = 'http://api.castle.dev/v2' }
15
-
16
- it { expect(config.url.host).to be_eql('api.castle.dev') }
17
- end
18
- end
19
-
20
- describe 'post' do
21
- context 'with default' do
22
- it { expect(config.url.port).to be_eql(443) }
23
- end
24
-
25
- context 'with setter' do
26
- before { config.url = 'http://api.castle.dev:3001/v2' }
27
-
28
- it { expect(config.url.port).to be_eql(3001) }
29
- end
30
- end
31
-
32
- describe 'api_secret' do
33
- context 'with env' do
34
- let(:secret_key_env) { 'secret_key_env' }
35
- let(:secret_key) { 'secret_key' }
36
-
37
- before do
38
- allow(ENV).to receive(:fetch).with(
39
- 'CASTLE_API_SECRET', ''
40
- ).and_return(secret_key_env)
41
- config.reset
42
- end
43
-
44
- it do
45
- expect(config.api_secret).to be_eql(secret_key_env)
46
- end
47
-
48
- context 'when key is overwritten' do
49
- before { config.api_secret = secret_key }
50
-
51
- it do
52
- expect(config.api_secret).to be_eql(secret_key)
53
- end
54
- end
55
- end
56
-
57
- context 'with setter' do
58
- let(:value) { 'new_secret' }
59
-
60
- before do
61
- config.api_secret = value
62
- end
63
-
64
- it do
65
- expect(config.api_secret).to be_eql(value)
66
- end
67
- end
68
-
69
- it do
70
- expect(config.api_secret).to be_eql('secret')
71
- end
72
- end
73
-
74
- describe 'request_timeout' do
75
- it do
76
- expect(config.request_timeout).to be_eql(500)
77
- end
78
-
79
- context 'with setter' do
80
- let(:value) { 50.0 }
81
-
82
- before do
83
- config.request_timeout = value
84
- end
85
-
86
- it do
87
- expect(config.request_timeout).to be_eql(value)
88
- end
89
- end
90
- end
91
-
92
- describe 'allowlisted' do
93
- it do
94
- expect(config.allowlisted.size).to be_eql(0)
95
- end
96
-
97
- context 'with setter' do
98
- before do
99
- config.allowlisted = ['header']
100
- end
101
-
102
- it do
103
- expect(config.allowlisted).to be_eql(['Header'])
104
- end
105
- end
106
- end
107
-
108
- describe 'denylisted' do
109
- it do
110
- expect(config.denylisted.size).to be_eql(0)
111
- end
112
-
113
- context 'with setter' do
114
- before do
115
- config.denylisted = ['header']
116
- end
117
-
118
- it do
119
- expect(config.denylisted).to be_eql(['Header'])
120
- end
121
- end
122
- end
123
-
124
- describe 'failover_strategy' do
125
- it do
126
- expect(config.failover_strategy).to be_eql(:allow)
127
- end
128
-
129
- context 'with setter' do
130
- before do
131
- config.failover_strategy = :deny
132
- end
133
-
134
- it do
135
- expect(config.failover_strategy).to be_eql(:deny)
136
- end
137
- end
138
-
139
- context 'when broken' do
140
- it do
141
- expect do
142
- config.failover_strategy = :unicorn
143
- end.to raise_error(Castle::ConfigurationError)
144
- end
145
- end
146
- end
13
+ it { expect(config.api_secret).to be_eql('') }
147
14
  end
@@ -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