drillbit 2.11.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/drillbit.rb +1 -0
- data/lib/drillbit/accept_header.rb +1 -0
- data/lib/drillbit/authorizable_resource.rb +61 -60
- data/lib/drillbit/authorizers/parameters.rb +1 -0
- data/lib/drillbit/authorizers/parameters/filtering.rb +7 -6
- data/lib/drillbit/authorizers/parameters/inclusions.rb +6 -9
- data/lib/drillbit/authorizers/parameters/resource.rb +20 -19
- data/lib/drillbit/authorizers/query.rb +1 -0
- data/lib/drillbit/authorizers/scope.rb +5 -4
- data/lib/drillbit/compatibility/controllers.rb +1 -0
- data/lib/drillbit/configuration.rb +14 -16
- data/lib/drillbit/errors/invalid_api_request.rb +1 -0
- data/lib/drillbit/errors/invalid_request_body.rb +1 -0
- data/lib/drillbit/errors/invalid_subdomain.rb +1 -0
- data/lib/drillbit/errors/invalid_token.rb +1 -0
- data/lib/drillbit/errors/unpermitted_inclusions.rb +1 -0
- data/lib/drillbit/matchers/accept_header.rb +1 -0
- data/lib/drillbit/matchers/generic.rb +4 -3
- data/lib/drillbit/matchers/subdomain.rb +5 -6
- data/lib/drillbit/matchers/version.rb +3 -2
- data/lib/drillbit/middleware/api_request_validator.rb +4 -3
- data/lib/drillbit/middleware/parameter_parser.rb +1 -0
- data/lib/drillbit/middleware/token_processor.rb +1 -0
- data/lib/drillbit/parameters/filter.rb +12 -11
- data/lib/drillbit/parameters/index.rb +3 -2
- data/lib/drillbit/parameters/page.rb +1 -0
- data/lib/drillbit/parameters/sort.rb +1 -0
- data/lib/drillbit/requests/base.rb +1 -1
- data/lib/drillbit/requests/rack.rb +3 -0
- data/lib/drillbit/requests/rails.rb +1 -0
- data/lib/drillbit/resource.rb +1 -0
- data/lib/drillbit/resource/model.rb +5 -4
- data/lib/drillbit/resource/naming.rb +11 -10
- data/lib/drillbit/resource/processors/filtering.rb +1 -0
- data/lib/drillbit/resource/processors/indexing.rb +1 -0
- data/lib/drillbit/resource/processors/paging.rb +4 -3
- data/lib/drillbit/resource/processors/sorting.rb +1 -0
- data/lib/drillbit/responses/invalid_api_request.rb +3 -0
- data/lib/drillbit/responses/invalid_request_body.rb +3 -0
- data/lib/drillbit/responses/invalid_subdomain.rb +3 -0
- data/lib/drillbit/responses/invalid_token.rb +3 -0
- data/lib/drillbit/serializers/json_api.rb +12 -11
- data/lib/drillbit/tokens/base64.rb +1 -0
- data/lib/drillbit/tokens/base64s/invalid.rb +1 -0
- data/lib/drillbit/tokens/base64s/null.rb +1 -0
- data/lib/drillbit/tokens/invalid.rb +1 -0
- data/lib/drillbit/tokens/json_web_token.rb +6 -5
- data/lib/drillbit/tokens/json_web_tokens/invalid.rb +1 -0
- data/lib/drillbit/tokens/json_web_tokens/null.rb +1 -0
- data/lib/drillbit/tokens/json_web_tokens/password_reset.rb +1 -0
- data/lib/drillbit/tokens/null.rb +1 -0
- data/lib/drillbit/utilities/string.rb +1 -0
- data/lib/drillbit/version.rb +2 -1
- metadata +28 -94
- metadata.gz.sig +0 -0
- data/Rakefile +0 -2
- data/spec/drillbit/accept_header_spec.rb +0 -119
- data/spec/drillbit/authorizers/parameters/filtering_spec.rb +0 -101
- data/spec/drillbit/authorizers/parameters/resource_spec.rb +0 -12
- data/spec/drillbit/authorizers/parameters_spec.rb +0 -19
- data/spec/drillbit/authorizers/query_spec.rb +0 -24
- data/spec/drillbit/authorizers/scope_spec.rb +0 -21
- data/spec/drillbit/errors/invalid_api_request_spec.rb +0 -31
- data/spec/drillbit/errors/invalid_request_body_spec.rb +0 -25
- data/spec/drillbit/errors/invalid_subdomain_spec.rb +0 -30
- data/spec/drillbit/errors/invalid_token_spec.rb +0 -24
- data/spec/drillbit/invalid_subdomain_spec.rb +0 -45
- data/spec/drillbit/invalid_token_spec.rb +0 -44
- data/spec/drillbit/matchers/accept_header_spec.rb +0 -114
- data/spec/drillbit/matchers/subdomain_spec.rb +0 -78
- data/spec/drillbit/matchers/version_spec.rb +0 -86
- data/spec/drillbit/middleware/api_request_validator_spec.rb +0 -185
- data/spec/drillbit/middleware/parameter_parser_spec.rb +0 -200
- data/spec/drillbit/middleware/token_processor_spec.rb +0 -27
- data/spec/drillbit/requests/base_spec.rb +0 -37
- data/spec/drillbit/requests/rack_spec.rb +0 -252
- data/spec/drillbit/requests/rails_spec.rb +0 -264
- data/spec/drillbit/resource/model_spec.rb +0 -64
- data/spec/drillbit/resource/processors/filtering_spec.rb +0 -106
- data/spec/drillbit/resource/processors/indexing_spec.rb +0 -45
- data/spec/drillbit/resource/processors/paging_spec.rb +0 -74
- data/spec/drillbit/resource/processors/sorting_spec.rb +0 -66
- data/spec/drillbit/tokens/base64_spec.rb +0 -44
- data/spec/drillbit/tokens/json_web_token_spec.rb +0 -231
- data/spec/drillbit/tokens/json_web_tokens/password_reset_spec.rb +0 -43
- data/spec/fixtures/test_rsa_key +0 -27
- data/spec/fixtures/test_rsa_key.pub +0 -9
- data/spec/spec_helper.rb +0 -4
- data/spec/support/private_keys.rb +0 -42
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'rspeckled/spec_helpers/rspeckled'
|
3
|
-
require 'drillbit/resource/model'
|
4
|
-
|
5
|
-
module Drillbit
|
6
|
-
module Resource
|
7
|
-
describe Model do
|
8
|
-
it 'can chain multiple processors together' do
|
9
|
-
resource = double
|
10
|
-
processed_resource = double
|
11
|
-
|
12
|
-
model = Model.new(resource: resource,
|
13
|
-
parameters: {
|
14
|
-
'filter' => {
|
15
|
-
'query' => 'my_query',
|
16
|
-
'single_arity' => true,
|
17
|
-
'multiple_arity' => 'multi',
|
18
|
-
},
|
19
|
-
'sort' => 'my_attribute',
|
20
|
-
'page' => {
|
21
|
-
'number' => 10,
|
22
|
-
'size' => 100,
|
23
|
-
},
|
24
|
-
})
|
25
|
-
|
26
|
-
allow(resource).to receive(:single_arity).
|
27
|
-
and_return(resource)
|
28
|
-
allow(resource).to receive(:multiple_arity).
|
29
|
-
with('multi').
|
30
|
-
and_return(resource)
|
31
|
-
allow(resource).to receive(:order).
|
32
|
-
with('my_attribute' => 'asc').
|
33
|
-
and_return(resource)
|
34
|
-
allow(resource).to receive(:page).
|
35
|
-
with(10).
|
36
|
-
and_return(resource)
|
37
|
-
allow(resource).to receive(:per).
|
38
|
-
with(100).
|
39
|
-
and_return(resource)
|
40
|
-
allow(resource).to receive(:for_query).
|
41
|
-
with('my_query').
|
42
|
-
and_return(processed_resource)
|
43
|
-
|
44
|
-
allow(processed_resource).to receive(:total_pages).
|
45
|
-
and_return(10)
|
46
|
-
allow(processed_resource).to receive(:current_page).
|
47
|
-
and_return(5)
|
48
|
-
allow(processed_resource).to receive(:prev_page).
|
49
|
-
and_return(4)
|
50
|
-
allow(processed_resource).to receive(:next_page).
|
51
|
-
and_return(6)
|
52
|
-
|
53
|
-
expect(model.processed).to eql processed_resource
|
54
|
-
expect(model.meta).to eql(
|
55
|
-
'current-page' => 5,
|
56
|
-
'total-pages' => 10,
|
57
|
-
'previous-page' => 4,
|
58
|
-
'next-page' => 6,
|
59
|
-
'sort' => { 'my_attribute' => 'asc' },
|
60
|
-
)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,106 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'rspeckled/spec_helpers/rspeckled'
|
3
|
-
require 'drillbit/resource/processors/filtering'
|
4
|
-
|
5
|
-
module Drillbit
|
6
|
-
module Resource
|
7
|
-
module Processors
|
8
|
-
describe Filtering do
|
9
|
-
let(:filtering_resource) { double }
|
10
|
-
|
11
|
-
it 'can return the resource if not filtered parameters are passed in' do
|
12
|
-
filtering = Filtering.new(filtering_resource)
|
13
|
-
|
14
|
-
expect(filtering.processed).to eql filtering_resource
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'can return a queried resource' do
|
18
|
-
filtering = Filtering.new(filtering_resource,
|
19
|
-
'filter' => {
|
20
|
-
'stuff' => 'blah',
|
21
|
-
})
|
22
|
-
|
23
|
-
allow(filtering_resource).to receive(:for_stuff).
|
24
|
-
with('blah').
|
25
|
-
and_return 'stuffed'
|
26
|
-
|
27
|
-
expect(filtering.processed).to eql 'stuffed'
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'does not try to query if the resource cannot query for that thing' do
|
31
|
-
filtering = Filtering.new(filtering_resource,
|
32
|
-
'filter' => {
|
33
|
-
'whatever' => 'blah',
|
34
|
-
})
|
35
|
-
|
36
|
-
expect(filtering.processed).to eql filtering_resource
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'can query for something that does not take arguments' do
|
40
|
-
filtering = Filtering.new(filtering_resource,
|
41
|
-
'filter' => {
|
42
|
-
'stuff' => 'blah',
|
43
|
-
})
|
44
|
-
|
45
|
-
allow(filtering_resource).to receive(:stuff).
|
46
|
-
and_return 'stuffed'
|
47
|
-
|
48
|
-
expect(filtering.processed).to eql 'stuffed'
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'can query for something that does not take arguments' do
|
52
|
-
filtering = Filtering.new(filtering_resource,
|
53
|
-
'filter' => {
|
54
|
-
'stuff' => 'blah',
|
55
|
-
'other_stuff' => 'other_blah',
|
56
|
-
})
|
57
|
-
|
58
|
-
allow(filtering_resource).to receive(:for_stuff).
|
59
|
-
with('blah').
|
60
|
-
and_return filtering_resource
|
61
|
-
allow(filtering_resource).to receive(:other_stuff).
|
62
|
-
and_return 'other_stuffed'
|
63
|
-
|
64
|
-
expect(filtering.processed).to eql 'other_stuffed'
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'can properly format numerical ranges' do
|
68
|
-
filtering = Filtering.new(filtering_resource,
|
69
|
-
'filter' => {
|
70
|
-
'stuff' => '100...200',
|
71
|
-
'infinity' => '9...Infinity',
|
72
|
-
'other_stuff' => '3_333.33..8_8__8.0',
|
73
|
-
})
|
74
|
-
|
75
|
-
allow(filtering_resource).to receive(:for_stuff).
|
76
|
-
with(100.0...200.0).
|
77
|
-
and_return filtering_resource
|
78
|
-
allow(filtering_resource).to receive(:infinity).
|
79
|
-
with(9.0...9_999_999).
|
80
|
-
and_return filtering_resource
|
81
|
-
allow(filtering_resource).to receive(:other_stuff).
|
82
|
-
with(3333.33..888.0).
|
83
|
-
and_return 'other_stuffed'
|
84
|
-
|
85
|
-
expect(filtering.processed).to eql 'other_stuffed'
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'can handle objects (eg ActiveRelation) that store their proxy class in klass' do
|
89
|
-
resource_class = double
|
90
|
-
filtering = Filtering.new(filtering_resource,
|
91
|
-
'filter' => {
|
92
|
-
'stuff' => 'blah',
|
93
|
-
})
|
94
|
-
|
95
|
-
allow(filtering_resource).to receive(:klass).
|
96
|
-
and_return(resource_class)
|
97
|
-
allow(resource_class).to receive(:stuff)
|
98
|
-
allow(filtering_resource).to receive(:stuff).
|
99
|
-
and_return 'stuffed'
|
100
|
-
|
101
|
-
expect(filtering.processed).to eql 'stuffed'
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'rspeckled/spec_helpers/rspeckled'
|
3
|
-
require 'drillbit/resource/processors/indexing'
|
4
|
-
|
5
|
-
module Drillbit
|
6
|
-
class TestIndexClass
|
7
|
-
def for_query(_param); end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
module Drillbit
|
12
|
-
module Resource
|
13
|
-
module Processors
|
14
|
-
describe Indexing do
|
15
|
-
let(:indexing_resource) { double }
|
16
|
-
|
17
|
-
it 'does not do anything if indexing params are not passed in' do
|
18
|
-
indexing = Indexing.new(indexing_resource)
|
19
|
-
|
20
|
-
expect(indexing.processed).to eql indexing_resource
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'does not do anything if indexing params are passed in but they are blank' do
|
24
|
-
indexing = Indexing.new(indexing_resource,
|
25
|
-
'filter' => {
|
26
|
-
'query' => '',
|
27
|
-
})
|
28
|
-
|
29
|
-
expect(indexing.processed).to eql indexing_resource
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'forces a query even if no parameters were passed in' do
|
33
|
-
indexing_resource = TestIndexClass.new
|
34
|
-
indexing = Indexing.new(indexing_resource)
|
35
|
-
|
36
|
-
allow(indexing_resource).to receive(:for_query).
|
37
|
-
with('*').
|
38
|
-
and_return('blah')
|
39
|
-
|
40
|
-
expect(indexing.processed).to eql 'blah'
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'rspeckled/spec_helpers/rspeckled'
|
3
|
-
require 'drillbit/resource/processors/paging'
|
4
|
-
|
5
|
-
module Drillbit
|
6
|
-
module Resource
|
7
|
-
module Processors
|
8
|
-
describe Paging do
|
9
|
-
let(:paging_resource) { double }
|
10
|
-
let(:processed_resource) { double }
|
11
|
-
|
12
|
-
it 'can return a default page' do
|
13
|
-
paging = Paging.new(paging_resource,
|
14
|
-
'page' => {
|
15
|
-
'size' => 10,
|
16
|
-
})
|
17
|
-
|
18
|
-
allow(paging_resource).to receive(:total_pages).and_return 10
|
19
|
-
allow(paging_resource).to receive(:current_page).and_return 1
|
20
|
-
allow(paging_resource).to receive(:prev_page).and_return nil
|
21
|
-
allow(paging_resource).to receive(:next_page).and_return nil
|
22
|
-
|
23
|
-
allow(paging_resource).to receive(:page).
|
24
|
-
with(1).
|
25
|
-
and_return paging_resource
|
26
|
-
allow(paging_resource).to receive(:per).
|
27
|
-
with(10).
|
28
|
-
and_return processed_resource
|
29
|
-
|
30
|
-
expect(paging.processed).to eql processed_resource
|
31
|
-
expect(paging.meta).to eql(
|
32
|
-
'total-pages' => 10,
|
33
|
-
'current-page' => 1,
|
34
|
-
'previous-page' => nil,
|
35
|
-
'next-page' => nil,
|
36
|
-
)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'can return a pageed resource' do
|
40
|
-
paging = Paging.new(paging_resource,
|
41
|
-
'page' => {
|
42
|
-
'number' => 5,
|
43
|
-
'size' => 10,
|
44
|
-
})
|
45
|
-
|
46
|
-
allow(paging_resource).to receive(:page).
|
47
|
-
with(5).
|
48
|
-
and_return paging_resource
|
49
|
-
allow(paging_resource).to receive(:per).
|
50
|
-
with(10).
|
51
|
-
and_return processed_resource
|
52
|
-
|
53
|
-
expect(paging.processed).to eql processed_resource
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'does not consider non-ideomatic page params as valid' do
|
57
|
-
paging = Paging.new(paging_resource,
|
58
|
-
'page' => {
|
59
|
-
'nombre' => 5,
|
60
|
-
'tamano' => 10,
|
61
|
-
})
|
62
|
-
|
63
|
-
expect(paging.processed).to eql paging_resource
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'does not do anything if page params are not passed in' do
|
67
|
-
paging = Paging.new(paging_resource)
|
68
|
-
|
69
|
-
expect(paging.processed).to eql paging_resource
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'rspeckled/spec_helpers/rspeckled'
|
3
|
-
require 'drillbit/resource/processors/sorting'
|
4
|
-
|
5
|
-
module Drillbit
|
6
|
-
module Resource
|
7
|
-
module Processors
|
8
|
-
describe Sorting do
|
9
|
-
let(:sorting_resource) { double }
|
10
|
-
|
11
|
-
it 'can return an ascending sort' do
|
12
|
-
sorting = Sorting.new(sorting_resource, 'sort' => 'my_attribute')
|
13
|
-
|
14
|
-
allow(sorting_resource).to receive(:order).
|
15
|
-
with('my_attribute' => 'asc').
|
16
|
-
and_return('sorted')
|
17
|
-
|
18
|
-
expect(sorting.processed).to eql 'sorted'
|
19
|
-
expect(sorting.meta).to eql(
|
20
|
-
'sort' => {
|
21
|
-
'my_attribute' => 'asc',
|
22
|
-
},
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'can return a descending sort' do
|
27
|
-
sorting = Sorting.new(sorting_resource, 'sort' => '-my_attribute')
|
28
|
-
|
29
|
-
allow(sorting_resource).to receive(:order).
|
30
|
-
with('my_attribute' => 'desc').
|
31
|
-
and_return('sorted')
|
32
|
-
|
33
|
-
expect(sorting.processed).to eql 'sorted'
|
34
|
-
expect(sorting.meta).to eql(
|
35
|
-
'sort' => {
|
36
|
-
'my_attribute' => 'desc',
|
37
|
-
},
|
38
|
-
)
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'can return multiple sorts' do
|
42
|
-
sorting = Sorting.new(sorting_resource, 'sort' => '-my_attribute,my_other_attribute')
|
43
|
-
|
44
|
-
allow(sorting_resource).to receive(:order).
|
45
|
-
with('my_attribute' => 'desc',
|
46
|
-
'my_other_attribute' => 'asc').
|
47
|
-
and_return('sorted')
|
48
|
-
|
49
|
-
expect(sorting.processed).to eql 'sorted'
|
50
|
-
expect(sorting.meta).to eql(
|
51
|
-
'sort' => {
|
52
|
-
'my_attribute' => 'desc',
|
53
|
-
'my_other_attribute' => 'asc',
|
54
|
-
},
|
55
|
-
)
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'does not do anything if sorting params are not passed in' do
|
59
|
-
sorting = Sorting.new(sorting_resource)
|
60
|
-
|
61
|
-
expect(sorting.processed).to eql sorting_resource
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'rspeckled/spec_helpers/rspeckled'
|
3
|
-
require 'drillbit/tokens/base64'
|
4
|
-
|
5
|
-
module Drillbit
|
6
|
-
module Tokens
|
7
|
-
describe Base64 do
|
8
|
-
it 'is valid' do
|
9
|
-
expect(Base64.new(token: 'foo')).to be_valid
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'is not blank' do
|
13
|
-
expect(Base64.new(token: 'foo')).not_to be_blank
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'can convert itself into a hash' do
|
17
|
-
token = Base64.new(token: 'foo')
|
18
|
-
|
19
|
-
expect(token.to_h).to eql([
|
20
|
-
{
|
21
|
-
'token' => 'foo',
|
22
|
-
},
|
23
|
-
{
|
24
|
-
'typ' => 'base64',
|
25
|
-
},
|
26
|
-
])
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'can convert itself into a null token' do
|
30
|
-
token = Base64.convert(raw_token: nil)
|
31
|
-
|
32
|
-
expect(token).to be_valid
|
33
|
-
expect(token).to be_blank
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'can convert itself into an invalid token' do
|
37
|
-
token = Base64.convert(raw_token: 'bla.h')
|
38
|
-
|
39
|
-
expect(token).not_to be_valid
|
40
|
-
expect(token).not_to be_blank
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,231 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'rspeckled/spec_helpers/rspeckled'
|
3
|
-
require 'drillbit/tokens/json_web_token'
|
4
|
-
|
5
|
-
module Drillbit
|
6
|
-
module Tokens
|
7
|
-
describe JsonWebToken do
|
8
|
-
it 'can convert an empty encrypted token' do
|
9
|
-
token = JsonWebToken.from_jwe(nil,
|
10
|
-
private_key: test_private_key)
|
11
|
-
|
12
|
-
expect(token).to be_a JsonWebTokens::Null
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'can convert an invalid encrypted token' do
|
16
|
-
token = JsonWebToken.from_jwe(invalid_jwe_token,
|
17
|
-
private_key: test_private_key)
|
18
|
-
|
19
|
-
expect(token).to be_a JsonWebTokens::Invalid
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'can verify an expired encrypted token' do
|
23
|
-
expired_jwe = valid_jwe_token('exp' => 1.day.ago.to_i,
|
24
|
-
'baz' => 'bar')
|
25
|
-
token = JsonWebToken.from_jwe(expired_jwe,
|
26
|
-
private_key: test_private_key)
|
27
|
-
|
28
|
-
expect(token).to be_a JsonWebTokens::Invalid
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'can convert an invalidly signed encrypted token' do
|
32
|
-
other_private_key = OpenSSL::PKey::RSA.new(2048)
|
33
|
-
token = JsonWebToken.from_jwe(valid_jwe_token,
|
34
|
-
private_key: other_private_key)
|
35
|
-
|
36
|
-
expect(token).to be_a JsonWebTokens::Invalid
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'can convert a valid encrypted token' do
|
40
|
-
token = JsonWebToken.from_jwe(valid_jwe_token,
|
41
|
-
private_key: test_private_key)
|
42
|
-
|
43
|
-
expect(token).to be_a JsonWebToken
|
44
|
-
expect(token.to_h).to eql(
|
45
|
-
[
|
46
|
-
{
|
47
|
-
'bar' => 'baz',
|
48
|
-
},
|
49
|
-
{
|
50
|
-
'typ' => 'JWT',
|
51
|
-
'alg' => 'RS256',
|
52
|
-
},
|
53
|
-
],
|
54
|
-
)
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'can convert an empty signed token' do
|
58
|
-
token = JsonWebToken.from_jws(nil,
|
59
|
-
private_key: test_private_key)
|
60
|
-
|
61
|
-
expect(token).to be_a JsonWebTokens::Null
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'can convert a token with no data' do
|
65
|
-
token = JsonWebToken.build_from_request([{}, {}])
|
66
|
-
|
67
|
-
expect(token).to be_empty
|
68
|
-
expect(token).not_to be_present
|
69
|
-
expect(token).to be_blank
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'can verify an expired signed token' do
|
73
|
-
expired_jws = valid_jws_token('exp' => 1.day.ago.to_i,
|
74
|
-
'baz' => 'bar')
|
75
|
-
token = JsonWebToken.from_jws(expired_jws,
|
76
|
-
private_key: test_private_key)
|
77
|
-
|
78
|
-
expect(token).to be_a JsonWebTokens::Invalid
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'can convert an invalidly signed token' do
|
82
|
-
other_private_key = OpenSSL::PKey::RSA.new(2048)
|
83
|
-
token_signed_with_another_key = JsonWebToken.from_jws(valid_jws_token,
|
84
|
-
private_key: other_private_key)
|
85
|
-
invalid_token = JsonWebToken.from_jws(invalid_jws_token,
|
86
|
-
private_key: test_private_key)
|
87
|
-
|
88
|
-
expect(token_signed_with_another_key).to be_a JsonWebTokens::Invalid
|
89
|
-
expect(invalid_token).to be_a JsonWebTokens::Invalid
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'can convert a valid signed token' do
|
93
|
-
token = JsonWebToken.from_jws(valid_jws_token,
|
94
|
-
private_key: test_private_key)
|
95
|
-
|
96
|
-
expect(token).to be_a JsonWebToken
|
97
|
-
expect(token.to_h).to eql([{ 'bar' => 'baz' }, { 'typ' => 'JWT', 'alg' => 'RS256' }])
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'can transform into a JWT' do
|
101
|
-
token = JsonWebToken.new(data: { 'foo' => 'bar' },
|
102
|
-
private_key: test_private_key)
|
103
|
-
|
104
|
-
jwt = token.to_jwt
|
105
|
-
jwt_s = token.to_jwt_s
|
106
|
-
|
107
|
-
expect(jwt.to_h).to eql('foo' => 'bar')
|
108
|
-
expect(jwt_s).to eql('eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJmb28iOiJiYXIifQ.')
|
109
|
-
end
|
110
|
-
|
111
|
-
# rubocop:disable Metrics/LineLength
|
112
|
-
it 'can transform into a JWS and back' do
|
113
|
-
token = JsonWebToken.new(data: { 'foo' => 'bar' },
|
114
|
-
private_key: test_private_key)
|
115
|
-
|
116
|
-
jws = token.to_jws
|
117
|
-
jws_s = token.to_jws_s
|
118
|
-
|
119
|
-
expect(jws.to_h).to eql('foo' => 'bar')
|
120
|
-
expect(jws_s).to eql('eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.DhPBu9Bfha08hSoy1a8Ps5YGxv2_KJCoNALH8dzd8b_VgKCPRQlIaHZwQfS5N1yfZczc2EqXIhPma4I2i-L92oDxyugZYfhMH6XUXSgB6F7SU5WtiglQ8gfgxC_u_K5htD_6zpRaHi6UTNbG8NF3RFBYK9za4GFPPWQawRQpdH2CxjyZP6pilmkynLuKx0OeQbJf1yzdgn1cDt60M8uoZZTzPgoU598ilDjYEETwyGyCi79S3A3ix8oDaJLhM8stPOHLUeglKrkwxOFglzVs7bULjzxZlygZujsHfWu16cjp_P3b4TIH_hiH0-Cjin-EVt4va2TnfGJ8HDxHxzWn7g')
|
121
|
-
|
122
|
-
converted_token = JsonWebToken.from_jws(jws_s,
|
123
|
-
private_key: test_private_key)
|
124
|
-
|
125
|
-
expect(converted_token.to_h).to eql [
|
126
|
-
{ 'foo' => 'bar' },
|
127
|
-
{ 'typ' => 'JWT', 'alg' => 'RS256' },
|
128
|
-
]
|
129
|
-
end
|
130
|
-
# rubocop:enable Metrics/LineLength
|
131
|
-
|
132
|
-
# rubocop:disable Metrics/LineLength
|
133
|
-
it 'can transform into a JWE and back' do
|
134
|
-
token = JsonWebToken.new(data: { 'foo' => 'bar' },
|
135
|
-
private_key: test_private_key)
|
136
|
-
|
137
|
-
jwe = token.to_jwe
|
138
|
-
jwe_s = token.to_jwe_s
|
139
|
-
|
140
|
-
expect(jwe.plain_text).to eql('eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.DhPBu9Bfha08hSoy1a8Ps5YGxv2_KJCoNALH8dzd8b_VgKCPRQlIaHZwQfS5N1yfZczc2EqXIhPma4I2i-L92oDxyugZYfhMH6XUXSgB6F7SU5WtiglQ8gfgxC_u_K5htD_6zpRaHi6UTNbG8NF3RFBYK9za4GFPPWQawRQpdH2CxjyZP6pilmkynLuKx0OeQbJf1yzdgn1cDt60M8uoZZTzPgoU598ilDjYEETwyGyCi79S3A3ix8oDaJLhM8stPOHLUeglKrkwxOFglzVs7bULjzxZlygZujsHfWu16cjp_P3b4TIH_hiH0-Cjin-EVt4va2TnfGJ8HDxHxzWn7g')
|
141
|
-
|
142
|
-
converted_token = JsonWebToken.from_jwe(jwe_s,
|
143
|
-
private_key: test_private_key)
|
144
|
-
|
145
|
-
expect(converted_token.to_h).to eql [
|
146
|
-
{ 'foo' => 'bar' },
|
147
|
-
{ 'typ' => 'JWT', 'alg' => 'RS256' },
|
148
|
-
]
|
149
|
-
end
|
150
|
-
# rubocop:enable Metrics/LineLength
|
151
|
-
|
152
|
-
it 'can accept roles as a string but convert them to an array' do
|
153
|
-
token = JsonWebToken.new(data: { 'rol' => 'bar,baz' },
|
154
|
-
private_key: test_private_key)
|
155
|
-
|
156
|
-
expect(token.roles).to eql %w{bar baz}
|
157
|
-
|
158
|
-
jwe_s = token.to_jwe_s
|
159
|
-
|
160
|
-
converted_token = JsonWebToken.from_jwe(jwe_s,
|
161
|
-
private_key: test_private_key)
|
162
|
-
|
163
|
-
expect(converted_token.data['rol']).to eql 'bar,baz'
|
164
|
-
expect(converted_token.roles).to eql %w{bar baz}
|
165
|
-
end
|
166
|
-
|
167
|
-
it 'can build a token by explicitly specifying all the data', :time_mock do
|
168
|
-
token = JsonWebToken.build(id: 'test_id',
|
169
|
-
audience: 'audience',
|
170
|
-
expiration: 20.years.from_now,
|
171
|
-
issuer: 'issuer',
|
172
|
-
issued_at: 5.minutes.ago,
|
173
|
-
not_before: 1.month.ago,
|
174
|
-
owner: 'subject_id',
|
175
|
-
roles: %w{my_role},
|
176
|
-
subject: 'my_subject',
|
177
|
-
subject_id: 'subject_id',
|
178
|
-
token_private_key: test_private_key)
|
179
|
-
|
180
|
-
jwe_s = token.to_jwe_s
|
181
|
-
|
182
|
-
converted_token = JsonWebToken.from_jwe(jwe_s,
|
183
|
-
private_key: test_private_key)
|
184
|
-
|
185
|
-
expect(converted_token.to_h).to eql(
|
186
|
-
[
|
187
|
-
{
|
188
|
-
'aud' => 'audience',
|
189
|
-
'exp' => 1_974_477_600,
|
190
|
-
'iat' => 1_343_325_300,
|
191
|
-
'iss' => 'issuer',
|
192
|
-
'jti' => 'test_id',
|
193
|
-
'nbf' => 1_340_733_600,
|
194
|
-
'own' => 'subject_id',
|
195
|
-
'rol' => 'my_role',
|
196
|
-
'sid' => 'subject_id',
|
197
|
-
'sub' => 'my_subject',
|
198
|
-
},
|
199
|
-
{
|
200
|
-
'typ' => 'JWT',
|
201
|
-
'alg' => 'RS256',
|
202
|
-
},
|
203
|
-
],
|
204
|
-
)
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'can build a token by only specifying the subject ID', :time_mock do
|
208
|
-
token = JsonWebToken.build(subject_id: 'subject_id',
|
209
|
-
token_private_key: test_private_key)
|
210
|
-
|
211
|
-
jwe_s = token.to_jwe_s
|
212
|
-
|
213
|
-
converted_token = JsonWebToken.from_jwe(jwe_s,
|
214
|
-
private_key: test_private_key)
|
215
|
-
|
216
|
-
expect(converted_token.to_h).to include(
|
217
|
-
'aud' => 'public',
|
218
|
-
'exp' => 1_343_930_400,
|
219
|
-
'iat' => 1_343_325_600,
|
220
|
-
'iss' => 'drillbit',
|
221
|
-
'jti' => match(uuid_regex),
|
222
|
-
'nbf' => 1_343_325_600,
|
223
|
-
'own' => 'subject_id',
|
224
|
-
'rol' => 'standard',
|
225
|
-
'sid' => 'subject_id',
|
226
|
-
'sub' => 'User',
|
227
|
-
)
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|