castle-rb 2.3.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|