castle-rb 2.3.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +55 -9
- data/lib/castle.rb +17 -7
- data/lib/castle/api.rb +20 -22
- data/lib/castle/client.rb +50 -19
- data/lib/castle/command.rb +5 -0
- data/lib/castle/commands/authenticate.rb +25 -0
- data/lib/castle/commands/identify.rb +30 -0
- data/lib/castle/commands/review.rb +13 -0
- data/lib/castle/commands/track.rb +25 -0
- data/lib/castle/commands/with_context.rb +28 -0
- data/lib/castle/configuration.rb +46 -14
- data/lib/castle/context_merger.rb +13 -0
- data/lib/castle/default_context.rb +28 -0
- data/lib/castle/errors.rb +2 -0
- data/lib/castle/extractors/client_id.rb +4 -14
- data/lib/castle/extractors/headers.rb +6 -18
- data/lib/castle/failover_auth_response.rb +21 -0
- data/lib/castle/header_formatter.rb +9 -0
- data/lib/castle/request.rb +7 -13
- data/lib/castle/response.rb +2 -0
- data/lib/castle/review.rb +11 -0
- data/lib/castle/secure_mode.rb +11 -0
- data/lib/castle/support/hanami.rb +19 -0
- data/lib/castle/support/padrino.rb +1 -1
- data/lib/castle/support/rails.rb +1 -1
- data/lib/castle/support/sinatra.rb +4 -2
- data/lib/castle/utils.rb +55 -0
- data/lib/castle/utils/cloner.rb +11 -0
- data/lib/castle/utils/merger.rb +23 -0
- data/lib/castle/version.rb +1 -1
- data/spec/lib/castle/api_spec.rb +16 -25
- data/spec/lib/castle/client_spec.rb +175 -39
- data/spec/lib/castle/command_spec.rb +9 -0
- data/spec/lib/castle/commands/authenticate_spec.rb +106 -0
- data/spec/lib/castle/commands/identify_spec.rb +85 -0
- data/spec/lib/castle/commands/review_spec.rb +24 -0
- data/spec/lib/castle/commands/track_spec.rb +107 -0
- data/spec/lib/castle/configuration_spec.rb +75 -27
- data/spec/lib/castle/context_merger_spec.rb +34 -0
- data/spec/lib/castle/default_context_spec.rb +35 -0
- data/spec/lib/castle/extractors/client_id_spec.rb +13 -5
- data/spec/lib/castle/extractors/headers_spec.rb +6 -5
- data/spec/lib/castle/extractors/ip_spec.rb +2 -9
- data/spec/lib/castle/header_formatter_spec.rb +21 -0
- data/spec/lib/castle/request_spec.rb +12 -9
- data/spec/lib/castle/response_spec.rb +1 -3
- data/spec/lib/castle/review_spec.rb +23 -0
- data/spec/lib/castle/secure_mode_spec.rb +9 -0
- data/spec/lib/castle/utils/cloner_spec.rb +18 -0
- data/spec/lib/castle/utils/merger_spec.rb +13 -0
- data/spec/lib/castle/utils_spec.rb +156 -0
- data/spec/lib/castle/version_spec.rb +1 -5
- data/spec/lib/castle_spec.rb +8 -15
- data/spec/spec_helper.rb +3 -9
- metadata +46 -12
- data/lib/castle/cookie_store.rb +0 -52
- data/lib/castle/headers.rb +0 -39
- data/lib/castle/support.rb +0 -11
- data/lib/castle/system.rb +0 -36
- data/spec/lib/castle/headers_spec.rb +0 -82
- data/spec/lib/castle/system_spec.rb +0 -70
data/lib/castle/cookie_store.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Castle
|
4
|
-
module CookieStore
|
5
|
-
class Base
|
6
|
-
EXPIRATION_TIME = 20 * 365 * 24 * 60 * 60 # cookie expiration time 20y
|
7
|
-
|
8
|
-
def initialize(request, response)
|
9
|
-
@request = request
|
10
|
-
@response = response
|
11
|
-
end
|
12
|
-
|
13
|
-
def [](key)
|
14
|
-
@request.cookies[key]
|
15
|
-
end
|
16
|
-
|
17
|
-
def []=(key, value)
|
18
|
-
@request.cookies[key] = value
|
19
|
-
if value
|
20
|
-
@response.set_cookie(key,
|
21
|
-
value: value,
|
22
|
-
expires: Time.now + EXPIRATION_TIME,
|
23
|
-
path: '/')
|
24
|
-
else
|
25
|
-
@response.delete_cookie(key)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class Rack
|
31
|
-
def initialize(cookies)
|
32
|
-
@cookies = cookies
|
33
|
-
end
|
34
|
-
|
35
|
-
def [](key)
|
36
|
-
@cookies[key]
|
37
|
-
end
|
38
|
-
|
39
|
-
def []=(key, value)
|
40
|
-
if value
|
41
|
-
@cookies[key] = {
|
42
|
-
value: value,
|
43
|
-
expires: Time.now + EXPIRATION_TIME,
|
44
|
-
path: '/'
|
45
|
-
}
|
46
|
-
else
|
47
|
-
@cookies.delete(key)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
data/lib/castle/headers.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Castle
|
4
|
-
# setups headers for requests
|
5
|
-
class Headers
|
6
|
-
def initialize
|
7
|
-
@config = Castle.config
|
8
|
-
@headers = {
|
9
|
-
'Content-Type' => 'application/json',
|
10
|
-
'User-Agent' => "Castle/v1 RubyBindings/#{Castle::VERSION}"
|
11
|
-
}
|
12
|
-
end
|
13
|
-
|
14
|
-
def prepare(client_id, ip, castle_headers)
|
15
|
-
@headers.merge!(
|
16
|
-
'X-Castle-Client-Id' => client_id,
|
17
|
-
'X-Castle-Ip' => ip,
|
18
|
-
'X-Castle-Headers' => castle_headers,
|
19
|
-
'X-Castle-Client-User-Agent' => JSON.generate(client_user_agent),
|
20
|
-
'X-Castle-Source' => @config.source_header
|
21
|
-
)
|
22
|
-
@headers.delete_if { |_k, header_value| header_value.nil? }
|
23
|
-
@headers
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def client_user_agent
|
29
|
-
{
|
30
|
-
bindings_version: Castle::VERSION,
|
31
|
-
lang: 'ruby',
|
32
|
-
lang_version: Castle::System.ruby_version,
|
33
|
-
platform: Castle::System.platform,
|
34
|
-
publisher: 'castle',
|
35
|
-
uname: Castle::System.uname
|
36
|
-
}
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/lib/castle/support.rb
DELETED
data/lib/castle/system.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Castle
|
4
|
-
# Get information regarding system
|
5
|
-
module System
|
6
|
-
class << self
|
7
|
-
# Returns hardware name, nodename, operating system release,
|
8
|
-
# name and version
|
9
|
-
# @example Castle::System.uname #=>
|
10
|
-
# Linux server 3.18.44-vs2.3.7.5-beng #1 SMP
|
11
|
-
# Thu Oct 27 14:11:29 BST 2016 x86_64 GNU/Linux
|
12
|
-
def uname
|
13
|
-
`uname -a 2>/dev/null`.strip if platform =~ /linux|darwin/i
|
14
|
-
rescue Errno::ENOMEM # couldn't create subprocess
|
15
|
-
'uname lookup failed'
|
16
|
-
end
|
17
|
-
|
18
|
-
# Returns current system platform
|
19
|
-
# @example Castle::System.platform #=> 'x86_64-pc-linux-gnu'
|
20
|
-
def platform
|
21
|
-
begin
|
22
|
-
require 'rbconfig'
|
23
|
-
RbConfig::CONFIG['host'] || RUBY_PLATFORM
|
24
|
-
rescue LoadError
|
25
|
-
RUBY_PLATFORM
|
26
|
-
end.downcase
|
27
|
-
end
|
28
|
-
|
29
|
-
# Returns ruby version
|
30
|
-
# @example Castle::System.ruby_version #=> '2.4.1-p111 (2017-03-22)'
|
31
|
-
def ruby_version
|
32
|
-
"#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe Castle::Headers do
|
6
|
-
subject do
|
7
|
-
described_class.new
|
8
|
-
end
|
9
|
-
|
10
|
-
before do
|
11
|
-
allow(Castle.config).to receive(:source_header).and_return('web')
|
12
|
-
stub_const('Castle::VERSION', '2.2.0')
|
13
|
-
end
|
14
|
-
|
15
|
-
let(:ip) { '1.1.1.1' }
|
16
|
-
let(:castle_headers) { 'headers' }
|
17
|
-
let(:client_id) { 'some_id' }
|
18
|
-
|
19
|
-
let(:prepared_headers) do
|
20
|
-
subject.prepare(client_id, ip, castle_headers)
|
21
|
-
end
|
22
|
-
|
23
|
-
shared_examples 'for_header' do |header, value|
|
24
|
-
let(:header) { header }
|
25
|
-
|
26
|
-
it "has header #{header}" do
|
27
|
-
expect(prepared_headers[header]).to eql(value)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
it_behaves_like 'for_header', 'Content-Type', 'application/json'
|
31
|
-
it_behaves_like 'for_header', 'X-Castle-Client-Id', 'some_id'
|
32
|
-
it_behaves_like 'for_header', 'X-Castle-Ip', '1.1.1.1'
|
33
|
-
it_behaves_like 'for_header', 'X-Castle-Headers', 'headers'
|
34
|
-
it_behaves_like 'for_header', 'X-Castle-Source', 'web'
|
35
|
-
it_behaves_like 'for_header',
|
36
|
-
'User-Agent',
|
37
|
-
'Castle/v1 RubyBindings/2.2.0'
|
38
|
-
|
39
|
-
describe 'X-Castle-Client-User-Agent' do
|
40
|
-
let(:header) { 'X-Castle-Client-User-Agent' }
|
41
|
-
let(:prepared_header_parsed) { JSON.parse(prepared_headers[header]) }
|
42
|
-
|
43
|
-
before do
|
44
|
-
allow(Castle::System).to receive(:uname).and_return('name')
|
45
|
-
end
|
46
|
-
|
47
|
-
it { expect(prepared_header_parsed).to include('lang') }
|
48
|
-
it { expect(prepared_header_parsed).to include('lang_version') }
|
49
|
-
it { expect(prepared_header_parsed).to include('platform') }
|
50
|
-
it { expect(prepared_header_parsed).to include('publisher') }
|
51
|
-
it { expect(prepared_header_parsed['bindings_version']).to eql('2.2.0') }
|
52
|
-
it { expect(prepared_header_parsed['uname']).to eql('name') }
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'missing' do
|
56
|
-
shared_examples 'for_missing_header' do |header|
|
57
|
-
let(:header) { header }
|
58
|
-
|
59
|
-
it "it missing header #{header}" do
|
60
|
-
expect(prepared_headers.key?(header)).to be_falsey
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
context 'ip' do
|
65
|
-
let(:ip) { nil }
|
66
|
-
|
67
|
-
it_behaves_like 'for_missing_header', 'X-Castle-Ip'
|
68
|
-
end
|
69
|
-
|
70
|
-
context 'client_id' do
|
71
|
-
let(:client_id) { nil }
|
72
|
-
|
73
|
-
it_behaves_like 'for_missing_header', 'X-Castle-Cookie-Id'
|
74
|
-
end
|
75
|
-
|
76
|
-
context 'castle headers' do
|
77
|
-
let(:castle_headers) { nil }
|
78
|
-
|
79
|
-
it_behaves_like 'for_missing_header', 'X-Castle-Headers'
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe Castle::System do
|
6
|
-
describe '.uname' do
|
7
|
-
subject(:uname) { described_class.uname }
|
8
|
-
|
9
|
-
before { allow(described_class).to receive(:platform) { platform } }
|
10
|
-
|
11
|
-
context 'darwin' do
|
12
|
-
let(:platform) { 'x86_64-apple-darwin16.6.0' }
|
13
|
-
|
14
|
-
it { expect { uname }.not_to raise_error }
|
15
|
-
it { expect(uname).to be_kind_of(String) }
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'linux' do
|
19
|
-
let(:platform) { 'x86_64-pc-linux-gnu' }
|
20
|
-
|
21
|
-
it { expect { uname }.not_to raise_error }
|
22
|
-
it { expect(uname).to be_kind_of(String) }
|
23
|
-
end
|
24
|
-
|
25
|
-
context 'different' do
|
26
|
-
let(:platform) { 'different' }
|
27
|
-
|
28
|
-
it { expect { uname }.not_to raise_error }
|
29
|
-
it { expect(uname).to be_nil }
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'Errno::ENOMEM' do
|
33
|
-
let(:platform) { 'x86_64-pc-linux-gnu' }
|
34
|
-
|
35
|
-
before do
|
36
|
-
allow(described_class).to receive(:`).with(
|
37
|
-
'uname -a 2>/dev/null'
|
38
|
-
).and_raise(Errno::ENOMEM)
|
39
|
-
end
|
40
|
-
|
41
|
-
it { expect { uname }.not_to raise_error }
|
42
|
-
it { expect(uname).to be_kind_of(String) }
|
43
|
-
it { expect(uname).to eql('uname lookup failed') }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe '.platform' do
|
48
|
-
subject(:platform) { described_class.platform }
|
49
|
-
|
50
|
-
context 'rbconfig' do
|
51
|
-
it { expect(platform).to eq(RbConfig::CONFIG['host']) }
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'RUBY_PLATFORM' do
|
55
|
-
before { stub_const('RbConfig::CONFIG', host: nil) }
|
56
|
-
|
57
|
-
it { expect(platform).to eq(RUBY_PLATFORM) }
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe '.ruby_version' do
|
62
|
-
subject(:ruby_version) { described_class.ruby_version }
|
63
|
-
|
64
|
-
let(:version) do
|
65
|
-
"#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
|
66
|
-
end
|
67
|
-
|
68
|
-
it { expect(ruby_version).to eq(version) }
|
69
|
-
end
|
70
|
-
end
|