castle-rb 3.2.0 → 3.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a15270851803a5228a22931ccea95fc873bab7e1
4
- data.tar.gz: 03741fc4fda242401a8e33e3ffab915e59ef0809
2
+ SHA256:
3
+ metadata.gz: ef681fe4eea20aa8dacb69718809e49103e17060a5f2b0a57331982c9d36b59f
4
+ data.tar.gz: 6ab1e89bdefc563ce78ca7ae9666fb86f2b22ce0b740250a10f67fa3eaa1a98b
5
5
  SHA512:
6
- metadata.gz: 26b1cb4d6eeee9fff4d11f51f2fd6a2ed4f562a44754355d041653b4730fe99e07883d3759f14ec40e6923f94be2325c537a69d8aa37be25e372ca857657f219
7
- data.tar.gz: '089bd3ca463c5fccd1e62f7669fb18933e39bd83de93ad02c2a2bbe154a71135a488a33965b7a0184a9eaff5ce18e0434ee415192fad0aced90889ec8c0b716a'
6
+ metadata.gz: cbd67d2101f93caa9c3c793171759bdf0401313ff6c3dbccacc0843674a6ec36d8b0c63e1c705a54e7f27d0b10b59990b85131ad6f492f02ba1e8b2673679583
7
+ data.tar.gz: c56cbdb356049465687277a388d39c62fe41a90e8b02436c38568fd7d8e18e7f8fcd12ad37e5f87c6b6b2a0fce0651da1a2863d3f14034b90da41cc5a876cf6e
data/README.md CHANGED
@@ -122,7 +122,7 @@ end
122
122
 
123
123
  ```ruby
124
124
  request_context = ::Castle::Client.to_context(request)
125
- track_options = {
125
+ track_options = ::Castle::Client.to_options({
126
126
  event: '$login.succeeded',
127
127
  user_id: user.id,
128
128
  properties: {
@@ -131,6 +131,6 @@ track_options = {
131
131
  traits: {
132
132
  key: 'value'
133
133
  }
134
- }
134
+ })
135
135
  CastleTrackingWorker.perform_async(request_context, track_options)
136
136
  ```
@@ -3,6 +3,7 @@
3
3
  require 'openssl'
4
4
  require 'net/http'
5
5
  require 'json'
6
+ require 'time'
6
7
 
7
8
  require 'castle/version'
8
9
  require 'castle/errors'
@@ -10,9 +11,10 @@ require 'castle/command'
10
11
  require 'castle/utils'
11
12
  require 'castle/utils/merger'
12
13
  require 'castle/utils/cloner'
14
+ require 'castle/utils/timestamp'
13
15
  require 'castle/context_merger'
16
+ require 'castle/context_sanitizer'
14
17
  require 'castle/default_context'
15
- require 'castle/commands/with_context'
16
18
  require 'castle/commands/identify'
17
19
  require 'castle/commands/authenticate'
18
20
  require 'castle/commands/track'
@@ -4,19 +4,28 @@ module Castle
4
4
  class Client
5
5
  class << self
6
6
  def from_request(request, options = {})
7
- new(to_context(request, options), options[:do_not_track])
7
+ new(
8
+ to_context(request, options),
9
+ to_options(options)
10
+ )
8
11
  end
9
12
 
10
13
  def to_context(request, options = {})
11
14
  default_context = Castle::DefaultContext.new(request, options[:cookies]).call
12
- Castle::ContextMerger.new(default_context).call(options[:context] || {})
15
+ Castle::ContextMerger.call(default_context, options[:context])
16
+ end
17
+
18
+ def to_options(options = {})
19
+ options[:timestamp] ||= Castle::Utils::Timestamp.call
20
+ options
13
21
  end
14
22
  end
15
23
 
16
24
  attr_accessor :api
17
25
 
18
- def initialize(context, do_not_track = false)
19
- @do_not_track = do_not_track
26
+ def initialize(context, options = {})
27
+ @do_not_track = options[:do_not_track]
28
+ @timestamp = options[:timestamp]
20
29
  @context = context
21
30
  @api = API.new
22
31
  end
@@ -25,6 +34,7 @@ module Castle
25
34
  options = Castle::Utils.deep_symbolize_keys(options || {})
26
35
 
27
36
  if tracked?
37
+ options[:timestamp] ||= @timestamp if @timestamp
28
38
  command = Castle::Commands::Authenticate.new(@context).build(options)
29
39
  begin
30
40
  @api.request(command).merge(failover: false, failover_reason: nil)
@@ -40,6 +50,7 @@ module Castle
40
50
  options = Castle::Utils.deep_symbolize_keys(options || {})
41
51
 
42
52
  return unless tracked?
53
+ options[:timestamp] ||= @timestamp if @timestamp
43
54
 
44
55
  command = Castle::Commands::Identify.new(@context).build(options)
45
56
  @api.request(command)
@@ -49,6 +60,7 @@ module Castle
49
60
  options = Castle::Utils.deep_symbolize_keys(options || {})
50
61
 
51
62
  return unless tracked?
63
+ options[:timestamp] ||= @timestamp if @timestamp
52
64
 
53
65
  command = Castle::Commands::Track.new(@context).build(options)
54
66
  @api.request(command)
@@ -70,7 +82,7 @@ module Castle
70
82
 
71
83
  def setup_context(request, cookies, additional_context)
72
84
  default_context = Castle::DefaultContext.new(request, cookies).call
73
- Castle::ContextMerger.new(default_context).call(additional_context || {})
85
+ Castle::ContextMerger.call(default_context, additional_context)
74
86
  end
75
87
 
76
88
  def failover_response_or_raise(failover_response, error)
@@ -3,13 +3,19 @@
3
3
  module Castle
4
4
  module Commands
5
5
  class Authenticate
6
- include WithContext
6
+ def initialize(context)
7
+ @context = context
8
+ end
7
9
 
8
10
  def build(options = {})
9
11
  validate!(options)
10
- build_context!(options)
12
+ context = ContextMerger.call(@context, options[:context])
13
+ context = ContextSanitizer.call(context)
11
14
 
12
- Castle::Command.new('authenticate', options, :post)
15
+ Castle::Command.new('authenticate',
16
+ options.merge(context: context,
17
+ sent_at: Castle::Utils::Timestamp.call),
18
+ :post)
13
19
  end
14
20
 
15
21
  private
@@ -3,13 +3,19 @@
3
3
  module Castle
4
4
  module Commands
5
5
  class Identify
6
- include WithContext
6
+ def initialize(context)
7
+ @context = context
8
+ end
7
9
 
8
10
  def build(options = {})
9
11
  validate!(options)
10
- build_context!(options)
12
+ context = ContextMerger.call(@context, options[:context])
13
+ context = ContextSanitizer.call(context)
11
14
 
12
- Castle::Command.new('identify', options, :post)
15
+ Castle::Command.new('identify',
16
+ options.merge(context: context,
17
+ sent_at: Castle::Utils::Timestamp.call),
18
+ :post)
13
19
  end
14
20
 
15
21
  private
@@ -3,13 +3,19 @@
3
3
  module Castle
4
4
  module Commands
5
5
  class Track
6
- include WithContext
6
+ def initialize(context)
7
+ @context = context
8
+ end
7
9
 
8
10
  def build(options = {})
9
11
  validate!(options)
10
- build_context!(options)
12
+ context = ContextMerger.call(@context, options[:context])
13
+ context = ContextSanitizer.call(context)
11
14
 
12
- Castle::Command.new('track', options, :post)
15
+ Castle::Command.new('track',
16
+ options.merge(context: context,
17
+ sent_at: Castle::Utils::Timestamp.call),
18
+ :post)
13
19
  end
14
20
 
15
21
  private
@@ -2,12 +2,11 @@
2
2
 
3
3
  module Castle
4
4
  class ContextMerger
5
- def initialize(context)
6
- @main_context = Castle::Utils::Cloner.call(context)
7
- end
8
-
9
- def call(request_context)
10
- Castle::Utils::Merger.call(@main_context, request_context)
5
+ class << self
6
+ def call(initial_context, request_context)
7
+ main_context = Castle::Utils::Cloner.call(initial_context)
8
+ Castle::Utils::Merger.call(main_context, request_context || {})
9
+ end
11
10
  end
12
11
  end
13
12
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Castle
4
+ # removes not proper active flag values
5
+ class ContextSanitizer
6
+ class << self
7
+ def call(context)
8
+ sanitized_active_mode(context) || {}
9
+ end
10
+
11
+ private
12
+
13
+ def sanitized_active_mode(context)
14
+ return context unless context && context.key?(:active)
15
+ return context if [true, false].include?(context[:active])
16
+ context.reject { |key| key == :active }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -4,19 +4,19 @@ module Castle
4
4
  module Utils
5
5
  class Merger
6
6
  def self.call(first, second)
7
- Castle::Utils.deep_symbolize_keys!(first)
8
- Castle::Utils.deep_symbolize_keys!(second)
7
+ first_s = Castle::Utils.deep_symbolize_keys(first)
8
+ second_s = Castle::Utils.deep_symbolize_keys(second)
9
9
 
10
- second.each do |name, value|
10
+ second_s.each do |name, value|
11
11
  if value.nil?
12
- first.delete(name)
13
- elsif value.is_a?(Hash) && first[name].is_a?(Hash)
14
- call(first[name], value)
12
+ first_s.delete(name)
13
+ elsif value.is_a?(Hash) && first_s[name].is_a?(Hash)
14
+ first_s[name] = call(first_s[name], value)
15
15
  else
16
- first[name] = value
16
+ first_s[name] = value
17
17
  end
18
18
  end
19
- first
19
+ first_s
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Castle
4
+ module Utils
5
+ # generates proper timestamp
6
+ class Timestamp
7
+ def self.call
8
+ Time.now.utc.iso8601(3)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Castle
4
- VERSION = '3.2.0'
4
+ VERSION = '3.3.0'
5
5
  end
@@ -12,25 +12,40 @@ describe Castle::Client do
12
12
  end
13
13
  let(:request) { Rack::Request.new(env) }
14
14
  let(:client) { described_class.from_request(request) }
15
+ let(:request_to_context) { described_class.to_context(request) }
16
+ let(:client_with_user_timestamp) do
17
+ described_class.new(request_to_context, timestamp: time_user)
18
+ end
19
+ let(:client_with_no_timestamp) { described_class.new(request_to_context) }
20
+
15
21
  let(:headers) { { 'X-Forwarded-For' => ip.to_s } }
16
22
  let(:context) do
17
23
  {
18
24
  client_id: 'abcd',
19
25
  active: true,
20
26
  origin: 'web',
21
- headers: headers,
27
+ headers: { 'X-Forwarded-For': ip.to_s },
22
28
  ip: ip,
23
29
  library: { name: 'castle-rb', version: '2.2.0' }
24
30
  }
25
31
  end
26
32
 
33
+ let(:time_now) { Time.now }
34
+ let(:time_auto) { time_now.utc.iso8601(3) }
35
+ let(:time_user) { (Time.now - 10_000).utc.iso8601(3) }
36
+
27
37
  before do
38
+ Timecop.freeze(time_now)
28
39
  stub_const('Castle::VERSION', '2.2.0')
29
40
  stub_request(:any, /api.castle.io/).with(
30
41
  basic_auth: ['', 'secret']
31
42
  ).to_return(status: 200, body: '{}', headers: {})
32
43
  end
33
44
 
45
+ after do
46
+ Timecop.return
47
+ end
48
+
34
49
  describe 'parses the request' do
35
50
  before do
36
51
  allow(Castle::API).to receive(:new).and_call_original
@@ -42,8 +57,26 @@ describe Castle::Client do
42
57
  end
43
58
  end
44
59
 
60
+ describe 'to_context' do
61
+ it do
62
+ expect(described_class.to_context(request)).to eql(context)
63
+ end
64
+ end
65
+
66
+ describe 'to_options' do
67
+ let(:options) { { user_id: '1234', traits: { name: 'Jo' } } }
68
+ let(:result) { { user_id: '1234', traits: { name: 'Jo' }, timestamp: time_auto } }
69
+
70
+ it do
71
+ expect(described_class.to_options(options)).to eql(result)
72
+ end
73
+ end
74
+
45
75
  describe 'identify' do
46
- let(:request_body) { { user_id: '1234', context: context, traits: { name: 'Jo' } } }
76
+ let(:request_body) do
77
+ { user_id: '1234', timestamp: time_auto,
78
+ sent_at: time_auto, context: context, traits: { name: 'Jo' } }
79
+ end
47
80
 
48
81
  before { client.identify(options) }
49
82
 
@@ -55,6 +88,35 @@ describe Castle::Client do
55
88
  JSON.parse(req.body) == JSON.parse(request_body.to_json)
56
89
  end
57
90
  end
91
+
92
+ context 'when passed timestamp in options and no defined timestamp' do
93
+ let(:client) { client_with_no_timestamp }
94
+ let(:options) { { user_id: '1234', traits: { name: 'Jo' }, timestamp: time_user } }
95
+ let(:request_body) do
96
+ { user_id: '1234', traits: { name: 'Jo' }, context: context,
97
+ timestamp: time_user, sent_at: time_auto }
98
+ end
99
+
100
+ it do
101
+ assert_requested :post, 'https://api.castle.io/v1/identify', times: 1 do |req|
102
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
103
+ end
104
+ end
105
+ end
106
+
107
+ context 'with client initialized with timestamp' do
108
+ let(:client) { client_with_user_timestamp }
109
+ let(:request_body) do
110
+ { user_id: '1234', timestamp: time_user, sent_at: time_auto,
111
+ context: context, traits: { name: 'Jo' } }
112
+ end
113
+
114
+ it do
115
+ assert_requested :post, 'https://api.castle.io/v1/identify', times: 1 do |req|
116
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
117
+ end
118
+ end
119
+ end
58
120
  end
59
121
 
60
122
  context 'string keys' do
@@ -71,14 +133,46 @@ describe Castle::Client do
71
133
  describe 'authenticate' do
72
134
  let(:options) { { event: '$login.succeeded', user_id: '1234' } }
73
135
  let(:request_response) { client.authenticate(options) }
74
- let(:request_body) { { event: '$login.succeeded', user_id: '1234', context: context } }
136
+ let(:request_body) do
137
+ { event: '$login.succeeded', user_id: '1234', context: context,
138
+ timestamp: time_auto, sent_at: time_auto }
139
+ end
75
140
 
76
141
  context 'symbol keys' do
77
142
  before { request_response }
78
143
 
79
144
  it do
80
145
  assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
81
- req.body == request_body.to_json
146
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
147
+ end
148
+ end
149
+
150
+ context 'when passed timestamp in options and no defined timestamp' do
151
+ let(:client) { client_with_no_timestamp }
152
+ let(:options) { { event: '$login.succeeded', user_id: '1234', timestamp: time_user } }
153
+ let(:request_body) do
154
+ { event: '$login.succeeded', user_id: '1234', context: context,
155
+ timestamp: time_user, sent_at: time_auto }
156
+ end
157
+
158
+ it do
159
+ assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
160
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
161
+ end
162
+ end
163
+ end
164
+
165
+ context 'with client initialized with timestamp' do
166
+ let(:client) { client_with_user_timestamp }
167
+ let(:request_body) do
168
+ { event: '$login.succeeded', user_id: '1234', context: context,
169
+ timestamp: time_user, sent_at: time_auto }
170
+ end
171
+
172
+ it do
173
+ assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
174
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
175
+ end
82
176
  end
83
177
  end
84
178
  end
@@ -90,7 +184,7 @@ describe Castle::Client do
90
184
 
91
185
  it do
92
186
  assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
93
- req.body == request_body.to_json
187
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
94
188
  end
95
189
  end
96
190
  end
@@ -100,7 +194,7 @@ describe Castle::Client do
100
194
 
101
195
  it do
102
196
  assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
103
- req.body == request_body.to_json
197
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
104
198
  end
105
199
  end
106
200
 
@@ -159,7 +253,10 @@ describe Castle::Client do
159
253
  end
160
254
 
161
255
  describe 'track' do
162
- let(:request_body) { { event: '$login.succeeded', context: context, user_id: '1234' } }
256
+ let(:request_body) do
257
+ { event: '$login.succeeded', context: context, user_id: '1234',
258
+ timestamp: time_auto, sent_at: time_auto }
259
+ end
163
260
 
164
261
  before { client.track(options) }
165
262
 
@@ -171,6 +268,35 @@ describe Castle::Client do
171
268
  JSON.parse(req.body) == JSON.parse(request_body.to_json)
172
269
  end
173
270
  end
271
+
272
+ context 'when passed timestamp in options and no defined timestamp' do
273
+ let(:client) { client_with_no_timestamp }
274
+ let(:options) { { event: '$login.succeeded', user_id: '1234', timestamp: time_user } }
275
+ let(:request_body) do
276
+ { event: '$login.succeeded', user_id: '1234', context: context,
277
+ timestamp: time_user, sent_at: time_auto }
278
+ end
279
+
280
+ it do
281
+ assert_requested :post, 'https://api.castle.io/v1/track', times: 1 do |req|
282
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
283
+ end
284
+ end
285
+ end
286
+
287
+ context 'with client initialized with timestamp' do
288
+ let(:client) { client_with_user_timestamp }
289
+ let(:request_body) do
290
+ { event: '$login.succeeded', context: context, user_id: '1234',
291
+ timestamp: time_user, sent_at: time_auto }
292
+ end
293
+
294
+ it do
295
+ assert_requested :post, 'https://api.castle.io/v1/track', times: 1 do |req|
296
+ JSON.parse(req.body) == JSON.parse(request_body.to_json)
297
+ end
298
+ end
299
+ end
174
300
  end
175
301
 
176
302
  context 'string keys' do
@@ -4,7 +4,18 @@ describe Castle::Commands::Authenticate do
4
4
  subject(:instance) { described_class.new(context) }
5
5
 
6
6
  let(:context) { { test: { test1: '1' } } }
7
- let(:default_payload) { { event: '$login.authenticate', user_id: '1234' } }
7
+ let(:default_payload) { { event: '$login.authenticate', user_id: '1234', sent_at: time_auto } }
8
+
9
+ let(:time_now) { Time.now }
10
+ let(:time_auto) { time_now.utc.iso8601(3) }
11
+
12
+ before do
13
+ Timecop.freeze(time_now)
14
+ end
15
+
16
+ after do
17
+ Timecop.return
18
+ end
8
19
 
9
20
  describe '.build' do
10
21
  subject(:command) { instance.build(payload) }
@@ -4,7 +4,18 @@ describe Castle::Commands::Identify do
4
4
  subject(:instance) { described_class.new(context) }
5
5
 
6
6
  let(:context) { { test: { test1: '1' } } }
7
- let(:default_payload) { { user_id: '1234' } }
7
+ let(:default_payload) { { user_id: '1234', sent_at: time_auto } }
8
+
9
+ let(:time_now) { Time.now }
10
+ let(:time_auto) { time_now.utc.iso8601(3) }
11
+
12
+ before do
13
+ Timecop.freeze(time_now)
14
+ end
15
+
16
+ after do
17
+ Timecop.return
18
+ end
8
19
 
9
20
  describe '.build' do
10
21
  subject(:command) { instance.build(payload) }
@@ -4,7 +4,18 @@ describe Castle::Commands::Track do
4
4
  subject(:instance) { described_class.new(context) }
5
5
 
6
6
  let(:context) { { test: { test1: '1' } } }
7
- let(:default_payload) { { event: '$login.track' } }
7
+ let(:default_payload) { { event: '$login.track', sent_at: time_auto } }
8
+
9
+ let(:time_now) { Time.now }
10
+ let(:time_auto) { time_now.utc.iso8601(3) }
11
+
12
+ before do
13
+ Timecop.freeze(time_now)
14
+ end
15
+
16
+ after do
17
+ Timecop.return
18
+ end
8
19
 
9
20
  describe '#build' do
10
21
  subject(:command) { instance.build(payload) }
@@ -1,21 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe Castle::ContextMerger do
4
- subject(:command) { described_class.new('go', { id: '1' }, :post) }
5
-
6
4
  let(:first) { { test: { test1: { c: '4' } } } }
7
5
 
8
- context '.new' do
9
- subject(:instance) { described_class.new(first) }
10
-
11
- it { expect(instance.instance_variable_get(:@main_context)).to eq(first) }
12
- it do
13
- expect(instance.instance_variable_get(:@main_context).object_id).not_to eq(first.object_id)
14
- end
15
- end
16
-
17
6
  context '#call' do
18
- subject { described_class.new(first).call(second) }
7
+ subject { described_class.call(first, second) }
19
8
 
20
9
  let(:result) { { test: { test1: { c: '4', d: '5' } } } }
21
10
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::ContextSanitizer do
4
+ let(:paylod) { { test: 'test' } }
5
+
6
+ describe '#call' do
7
+ subject { described_class.call(context) }
8
+
9
+ context 'when active true' do
10
+ let(:context) { paylod.merge(active: true) }
11
+
12
+ it { is_expected.to eql(context) }
13
+ end
14
+
15
+ context 'when active false' do
16
+ let(:context) { paylod.merge(active: false) }
17
+
18
+ it { is_expected.to eql(context) }
19
+ end
20
+
21
+ context 'when active string' do
22
+ let(:context) { paylod.merge(active: 'uknown') }
23
+
24
+ it { is_expected.to eql(paylod) }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Utils::Timestamp do
4
+ subject { described_class.call }
5
+
6
+ let(:time_string) { '2018-01-10T14:14:24.407Z' }
7
+ let(:time) { Time.parse(time_string) }
8
+
9
+ before do
10
+ Timecop.freeze(time)
11
+ end
12
+
13
+ after do
14
+ Timecop.return
15
+ end
16
+
17
+ describe '#call' do
18
+ it do
19
+ is_expected.to eql(time_string)
20
+ end
21
+ end
22
+ end
@@ -5,6 +5,7 @@ require 'bundler/setup'
5
5
  require 'rack'
6
6
  require 'webmock/rspec'
7
7
  require 'byebug'
8
+ require 'timecop'
8
9
 
9
10
  require 'coveralls'
10
11
  Coveralls.wear!
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: castle-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.3.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-12-15 00:00:00.000000000 Z
11
+ date: 2018-01-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Castle protects your users from account compromise
14
14
  email: johan@castle.io
@@ -26,9 +26,9 @@ files:
26
26
  - lib/castle/commands/identify.rb
27
27
  - lib/castle/commands/review.rb
28
28
  - lib/castle/commands/track.rb
29
- - lib/castle/commands/with_context.rb
30
29
  - lib/castle/configuration.rb
31
30
  - lib/castle/context_merger.rb
31
+ - lib/castle/context_sanitizer.rb
32
32
  - lib/castle/default_context.rb
33
33
  - lib/castle/errors.rb
34
34
  - lib/castle/extractors/client_id.rb
@@ -47,6 +47,7 @@ files:
47
47
  - lib/castle/utils.rb
48
48
  - lib/castle/utils/cloner.rb
49
49
  - lib/castle/utils/merger.rb
50
+ - lib/castle/utils/timestamp.rb
50
51
  - lib/castle/version.rb
51
52
  - spec/lib/castle/api_spec.rb
52
53
  - spec/lib/castle/client_spec.rb
@@ -57,6 +58,7 @@ files:
57
58
  - spec/lib/castle/commands/track_spec.rb
58
59
  - spec/lib/castle/configuration_spec.rb
59
60
  - spec/lib/castle/context_merger_spec.rb
61
+ - spec/lib/castle/context_sanitizer_spec.rb
60
62
  - spec/lib/castle/default_context_spec.rb
61
63
  - spec/lib/castle/extractors/client_id_spec.rb
62
64
  - spec/lib/castle/extractors/headers_spec.rb
@@ -68,6 +70,7 @@ files:
68
70
  - spec/lib/castle/secure_mode_spec.rb
69
71
  - spec/lib/castle/utils/cloner_spec.rb
70
72
  - spec/lib/castle/utils/merger_spec.rb
73
+ - spec/lib/castle/utils/timestamp_spec.rb
71
74
  - spec/lib/castle/utils_spec.rb
72
75
  - spec/lib/castle/version_spec.rb
73
76
  - spec/lib/castle_spec.rb
@@ -92,32 +95,34 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
95
  version: '0'
93
96
  requirements: []
94
97
  rubyforge_project:
95
- rubygems_version: 2.6.13
98
+ rubygems_version: 2.7.4
96
99
  signing_key:
97
100
  specification_version: 4
98
101
  summary: Castle
99
102
  test_files:
100
- - spec/lib/castle/api_spec.rb
103
+ - spec/spec_helper.rb
104
+ - spec/lib/castle_spec.rb
105
+ - spec/lib/castle/context_sanitizer_spec.rb
106
+ - spec/lib/castle/review_spec.rb
101
107
  - 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
108
+ - spec/lib/castle/api_spec.rb
107
109
  - spec/lib/castle/configuration_spec.rb
108
- - spec/lib/castle/context_merger_spec.rb
110
+ - spec/lib/castle/version_spec.rb
109
111
  - spec/lib/castle/default_context_spec.rb
110
- - spec/lib/castle/extractors/client_id_spec.rb
111
- - spec/lib/castle/extractors/headers_spec.rb
112
- - spec/lib/castle/extractors/ip_spec.rb
113
112
  - spec/lib/castle/header_formatter_spec.rb
114
- - spec/lib/castle/request_spec.rb
115
- - spec/lib/castle/response_spec.rb
116
- - spec/lib/castle/review_spec.rb
117
- - spec/lib/castle/secure_mode_spec.rb
118
113
  - spec/lib/castle/utils/cloner_spec.rb
114
+ - spec/lib/castle/utils/timestamp_spec.rb
119
115
  - spec/lib/castle/utils/merger_spec.rb
116
+ - spec/lib/castle/command_spec.rb
117
+ - spec/lib/castle/request_spec.rb
118
+ - spec/lib/castle/response_spec.rb
119
+ - spec/lib/castle/commands/review_spec.rb
120
+ - spec/lib/castle/commands/authenticate_spec.rb
121
+ - spec/lib/castle/commands/track_spec.rb
122
+ - spec/lib/castle/commands/identify_spec.rb
123
+ - spec/lib/castle/context_merger_spec.rb
124
+ - spec/lib/castle/extractors/ip_spec.rb
125
+ - spec/lib/castle/extractors/headers_spec.rb
126
+ - spec/lib/castle/extractors/client_id_spec.rb
120
127
  - spec/lib/castle/utils_spec.rb
121
- - spec/lib/castle/version_spec.rb
122
- - spec/lib/castle_spec.rb
123
- - spec/spec_helper.rb
128
+ - spec/lib/castle/secure_mode_spec.rb
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- module WithContext
6
- def initialize(context)
7
- @context_merger = ContextMerger.new(context)
8
- end
9
-
10
- private
11
-
12
- def build_context!(options)
13
- sanitize_active_mode!(options)
14
- options[:context] = merge_context(options[:context])
15
- end
16
-
17
- def sanitize_active_mode!(options)
18
- return unless options[:context] && options[:context].key?(:active)
19
- return if [true, false].include?(options[:context][:active])
20
- options[:context].delete(:active)
21
- end
22
-
23
- def merge_context(request_context)
24
- @context_merger.call(request_context || {})
25
- end
26
- end
27
- end
28
- end