drillbit 2.11.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/drillbit.rb +1 -0
  5. data/lib/drillbit/accept_header.rb +1 -0
  6. data/lib/drillbit/authorizable_resource.rb +61 -60
  7. data/lib/drillbit/authorizers/parameters.rb +1 -0
  8. data/lib/drillbit/authorizers/parameters/filtering.rb +7 -6
  9. data/lib/drillbit/authorizers/parameters/inclusions.rb +6 -9
  10. data/lib/drillbit/authorizers/parameters/resource.rb +20 -19
  11. data/lib/drillbit/authorizers/query.rb +1 -0
  12. data/lib/drillbit/authorizers/scope.rb +5 -4
  13. data/lib/drillbit/compatibility/controllers.rb +1 -0
  14. data/lib/drillbit/configuration.rb +14 -16
  15. data/lib/drillbit/errors/invalid_api_request.rb +1 -0
  16. data/lib/drillbit/errors/invalid_request_body.rb +1 -0
  17. data/lib/drillbit/errors/invalid_subdomain.rb +1 -0
  18. data/lib/drillbit/errors/invalid_token.rb +1 -0
  19. data/lib/drillbit/errors/unpermitted_inclusions.rb +1 -0
  20. data/lib/drillbit/matchers/accept_header.rb +1 -0
  21. data/lib/drillbit/matchers/generic.rb +4 -3
  22. data/lib/drillbit/matchers/subdomain.rb +5 -6
  23. data/lib/drillbit/matchers/version.rb +3 -2
  24. data/lib/drillbit/middleware/api_request_validator.rb +4 -3
  25. data/lib/drillbit/middleware/parameter_parser.rb +1 -0
  26. data/lib/drillbit/middleware/token_processor.rb +1 -0
  27. data/lib/drillbit/parameters/filter.rb +12 -11
  28. data/lib/drillbit/parameters/index.rb +3 -2
  29. data/lib/drillbit/parameters/page.rb +1 -0
  30. data/lib/drillbit/parameters/sort.rb +1 -0
  31. data/lib/drillbit/requests/base.rb +1 -1
  32. data/lib/drillbit/requests/rack.rb +3 -0
  33. data/lib/drillbit/requests/rails.rb +1 -0
  34. data/lib/drillbit/resource.rb +1 -0
  35. data/lib/drillbit/resource/model.rb +5 -4
  36. data/lib/drillbit/resource/naming.rb +11 -10
  37. data/lib/drillbit/resource/processors/filtering.rb +1 -0
  38. data/lib/drillbit/resource/processors/indexing.rb +1 -0
  39. data/lib/drillbit/resource/processors/paging.rb +4 -3
  40. data/lib/drillbit/resource/processors/sorting.rb +1 -0
  41. data/lib/drillbit/responses/invalid_api_request.rb +3 -0
  42. data/lib/drillbit/responses/invalid_request_body.rb +3 -0
  43. data/lib/drillbit/responses/invalid_subdomain.rb +3 -0
  44. data/lib/drillbit/responses/invalid_token.rb +3 -0
  45. data/lib/drillbit/serializers/json_api.rb +12 -11
  46. data/lib/drillbit/tokens/base64.rb +1 -0
  47. data/lib/drillbit/tokens/base64s/invalid.rb +1 -0
  48. data/lib/drillbit/tokens/base64s/null.rb +1 -0
  49. data/lib/drillbit/tokens/invalid.rb +1 -0
  50. data/lib/drillbit/tokens/json_web_token.rb +6 -5
  51. data/lib/drillbit/tokens/json_web_tokens/invalid.rb +1 -0
  52. data/lib/drillbit/tokens/json_web_tokens/null.rb +1 -0
  53. data/lib/drillbit/tokens/json_web_tokens/password_reset.rb +1 -0
  54. data/lib/drillbit/tokens/null.rb +1 -0
  55. data/lib/drillbit/utilities/string.rb +1 -0
  56. data/lib/drillbit/version.rb +2 -1
  57. metadata +28 -94
  58. metadata.gz.sig +0 -0
  59. data/Rakefile +0 -2
  60. data/spec/drillbit/accept_header_spec.rb +0 -119
  61. data/spec/drillbit/authorizers/parameters/filtering_spec.rb +0 -101
  62. data/spec/drillbit/authorizers/parameters/resource_spec.rb +0 -12
  63. data/spec/drillbit/authorizers/parameters_spec.rb +0 -19
  64. data/spec/drillbit/authorizers/query_spec.rb +0 -24
  65. data/spec/drillbit/authorizers/scope_spec.rb +0 -21
  66. data/spec/drillbit/errors/invalid_api_request_spec.rb +0 -31
  67. data/spec/drillbit/errors/invalid_request_body_spec.rb +0 -25
  68. data/spec/drillbit/errors/invalid_subdomain_spec.rb +0 -30
  69. data/spec/drillbit/errors/invalid_token_spec.rb +0 -24
  70. data/spec/drillbit/invalid_subdomain_spec.rb +0 -45
  71. data/spec/drillbit/invalid_token_spec.rb +0 -44
  72. data/spec/drillbit/matchers/accept_header_spec.rb +0 -114
  73. data/spec/drillbit/matchers/subdomain_spec.rb +0 -78
  74. data/spec/drillbit/matchers/version_spec.rb +0 -86
  75. data/spec/drillbit/middleware/api_request_validator_spec.rb +0 -185
  76. data/spec/drillbit/middleware/parameter_parser_spec.rb +0 -200
  77. data/spec/drillbit/middleware/token_processor_spec.rb +0 -27
  78. data/spec/drillbit/requests/base_spec.rb +0 -37
  79. data/spec/drillbit/requests/rack_spec.rb +0 -252
  80. data/spec/drillbit/requests/rails_spec.rb +0 -264
  81. data/spec/drillbit/resource/model_spec.rb +0 -64
  82. data/spec/drillbit/resource/processors/filtering_spec.rb +0 -106
  83. data/spec/drillbit/resource/processors/indexing_spec.rb +0 -45
  84. data/spec/drillbit/resource/processors/paging_spec.rb +0 -74
  85. data/spec/drillbit/resource/processors/sorting_spec.rb +0 -66
  86. data/spec/drillbit/tokens/base64_spec.rb +0 -44
  87. data/spec/drillbit/tokens/json_web_token_spec.rb +0 -231
  88. data/spec/drillbit/tokens/json_web_tokens/password_reset_spec.rb +0 -43
  89. data/spec/fixtures/test_rsa_key +0 -27
  90. data/spec/fixtures/test_rsa_key.pub +0 -9
  91. data/spec/spec_helper.rb +0 -4
  92. data/spec/support/private_keys.rb +0 -42
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled'
3
- require 'drillbit/authorizers/parameters/filtering'
4
-
5
- module Drillbit
6
- module Authorizers
7
- class Parameters
8
- describe Filtering do
9
- let(:params) { { filter: { name: 'Bill', age: 26 } } }
10
-
11
- it 'can authorize new filter parameters', verify: false do
12
- filter_params = Filtering.new(action: 'index',
13
- token: '1234',
14
- user: '1234',
15
- issuer: 'my_issuer',
16
- params: params)
17
-
18
- allow(params).to receive(:permit)
19
-
20
- filter_params.send(:add_filterable_parameters, :name, :age)
21
- filter_params.call
22
-
23
- expect(params).to have_received(:permit).
24
- with(:sort,
25
- :token,
26
- :token_b64,
27
- :token_jwt,
28
- :format,
29
- :accept,
30
- :include,
31
- include(
32
- filter: include(:name, :age),
33
- ))
34
- end
35
-
36
- it 'can authorize parameters if they come in as arrays', verify: false do
37
- params = {
38
- filter: {
39
- name: 'Bill',
40
- ary: %w{hello},
41
- },
42
- }
43
- filter_params = Filtering.new(action: 'index',
44
- token: '1234',
45
- user: '1234',
46
- issuer: 'my_issuer',
47
- params: params)
48
-
49
- allow(params).to receive(:permit)
50
-
51
- filter_params.send(:add_filterable_parameters, :name, :ary)
52
- filter_params.call
53
-
54
- expect(params).to have_received(:permit).
55
- with(:sort,
56
- :token,
57
- :token_b64,
58
- :token_jwt,
59
- :format,
60
- :accept,
61
- :include,
62
- include(
63
- filter: include(:name, ary: []),
64
- ))
65
- end
66
-
67
- it 'has default authorized parameters', verify: false do
68
- filter_params = Filtering.new(action: 'index',
69
- token: '1234',
70
- user: '1234',
71
- issuer: 'my_issuer',
72
- params: params)
73
-
74
- allow(params).to receive(:permit)
75
-
76
- filter_params.call
77
-
78
- expect(params).to have_received(:permit).
79
- with(:sort,
80
- :token,
81
- :token_b64,
82
- :token_jwt,
83
- :format,
84
- :accept,
85
- :include,
86
- page: %i{
87
- number
88
- size
89
- offset
90
- limit
91
- cursor
92
- },
93
- filter: [
94
- :query,
95
- {},
96
- ])
97
- end
98
- end
99
- end
100
- end
101
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled'
3
- require 'drillbit/authorizers/parameters/resource'
4
-
5
- module Drillbit
6
- module Authorizers
7
- class Parameters
8
- describe Resource do
9
- end
10
- end
11
- end
12
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled'
3
- require 'drillbit/authorizers/parameters'
4
-
5
- module Drillbit
6
- module Authorizers
7
- describe Parameters do
8
- it 'defaults to nothing' do
9
- parameters = Parameters.new(action: 'index',
10
- token: '123',
11
- user: 'my_user',
12
- issuer: 'my_issuer',
13
- params: { foo: 'bar' })
14
-
15
- expect(parameters.call).to eql(foo: 'bar')
16
- end
17
- end
18
- end
19
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled'
3
- require 'drillbit/authorizers/query'
4
-
5
- module Drillbit
6
- module Authorizers
7
- describe Query do
8
- it 'does not authorize the resource by default' do
9
- authorizer = Query.new(action: 'index',
10
- token: '123',
11
- user: 'my_user',
12
- issuer: 'my_issuer',
13
- resource: 'my_resource',
14
- params: 'my_params')
15
-
16
- expect(authorizer).not_to be_able_to_index
17
- expect(authorizer).not_to be_able_to_show
18
- expect(authorizer).not_to be_able_to_create
19
- expect(authorizer).not_to be_able_to_update
20
- expect(authorizer).not_to be_able_to_destroy
21
- end
22
- end
23
- end
24
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled'
3
- require 'ostruct'
4
- require 'drillbit/authorizers/scope'
5
-
6
- module Drillbit
7
- module Authorizers
8
- describe Scope do
9
- it 'defaults to nothing' do
10
- scope = Scope.new(action: 'index',
11
- token: '123',
12
- user: Object.new,
13
- issuer: 'my_issuer',
14
- params: {},
15
- scope_root: OpenStruct.new(none: []))
16
-
17
- expect(scope.call).to be_empty
18
- end
19
- end
20
- end
21
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/errors/invalid_api_request'
4
-
5
- module Drillbit
6
- module Errors
7
- describe InvalidApiRequest do
8
- let(:error) { InvalidApiRequest.new }
9
-
10
- it 'has a status of 400' do
11
- expect(error.http_status).to eql 400
12
- end
13
-
14
- it 'has a code' do
15
- expect(error.code).to eql 'errors.invalid_api_request'
16
- end
17
-
18
- it 'can output the detail' do
19
- expect(error.detail).to eql 'The accept header that you passed in the ' \
20
- 'request cannot be parsed, please refer to ' \
21
- 'the documentation to verify.'
22
- end
23
-
24
- it 'can output the source' do
25
- error = InvalidApiRequest.new accept_header: 'foo'
26
-
27
- expect(error.source).to eql(accept_header: 'foo')
28
- end
29
- end
30
- end
31
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/errors/invalid_request_body'
4
-
5
- module Drillbit
6
- module Errors
7
- describe InvalidRequestBody do
8
- let(:error) { InvalidRequestBody.new }
9
-
10
- it 'has a status of 400' do
11
- expect(error.http_status).to eql 400
12
- end
13
-
14
- it 'has a code' do
15
- expect(error.code).to eql 'errors.invalid_request_body'
16
- end
17
-
18
- it 'can output the detail' do
19
- expect(error.detail).to eql \
20
- 'The information you attempted to send in the request cannot be parsed as ' \
21
- 'a valid JSON document.'
22
- end
23
- end
24
- end
25
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/errors/invalid_subdomain'
4
-
5
- module Drillbit
6
- module Errors
7
- describe InvalidSubdomain do
8
- let(:error) { InvalidSubdomain.new }
9
-
10
- it 'has a status of 404' do
11
- expect(error.http_status).to eql 404
12
- end
13
-
14
- it 'has a code' do
15
- expect(error.code).to eql 'errors.invalid_subdomain'
16
- end
17
-
18
- it 'can output the detail' do
19
- expect(error.detail).to eql \
20
- 'The subdomain you attempted to access is not valid. Please try again.'
21
- end
22
-
23
- it 'can output the source' do
24
- error = InvalidSubdomain.new http_host: 'foo'
25
-
26
- expect(error.source).to eql(http_host: 'foo')
27
- end
28
- end
29
- end
30
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/errors/invalid_token'
4
-
5
- module Drillbit
6
- module Errors
7
- describe InvalidToken do
8
- let(:error) { InvalidToken.new }
9
-
10
- it 'has a status of 401' do
11
- expect(error.http_status).to eql 401
12
- end
13
-
14
- it 'has a code' do
15
- expect(error.code).to eql 'errors.invalid_token'
16
- end
17
-
18
- it 'can output the detail' do
19
- expect(error.detail).to eql \
20
- 'Either the token you passed is invalid or is not allowed to perform this action.'
21
- end
22
- end
23
- end
24
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/responses/invalid_subdomain'
4
-
5
- module Drillbit
6
- module Responses
7
- describe InvalidSubdomain, singletons: Erratum::Configuration do
8
- it 'returns the proper response' do
9
- Erratum.configuration.url_mappings = {
10
- 'external_documentation_urls' => {
11
- 'errors.responses.invalid_subdomain' => 'http://example.com/foo',
12
- },
13
- 'developer_documentation_urls' => {
14
- 'errors.responses.invalid_subdomain' => 'http://example.com/foo',
15
- },
16
- }
17
-
18
- request = { 'HTTP_HOST' => 'api.example.com' }
19
- status, headers, response = InvalidSubdomain.call(request)
20
-
21
- expect(status).to eql 404
22
- expect(headers).to eql({})
23
- expect(JSON.load(response[0])).to include(
24
- 'errors' => [
25
- include(
26
- 'id' => match(/[a-f0-9\-]+/),
27
- 'links' => {
28
- 'about' => nil,
29
- 'documentation' => nil,
30
- },
31
- 'status' => 404,
32
- 'code' => 'errors.invalid_subdomain',
33
- 'title' => 'Invalid Subdomain',
34
- 'detail' => 'The subdomain you attempted to access is not valid.' \
35
- ' Please try again.',
36
- 'source' => {
37
- 'http_host' => 'api.example.com',
38
- },
39
- ),
40
- ],
41
- )
42
- end
43
- end
44
- end
45
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/responses/invalid_token'
4
-
5
- # rubocop:disable Metrics/LineLength
6
- module Drillbit
7
- module Responses
8
- describe InvalidToken, singletons: Erratum::Configuration do
9
- it 'returns the proper response' do
10
- Erratum.configuration.url_mappings = {
11
- 'external_documentation_urls' => {
12
- 'errors.responses.invalid_token' => 'http://example.com/foo',
13
- },
14
- 'developer_documentation_urls' => {
15
- 'errors.responses.invalid_token' => 'http://example.com/foo',
16
- },
17
- }
18
-
19
- request = { 'HTTP_HOST' => 'api.example.com' }
20
- status, headers, response = InvalidToken.call(request, application_name: 'my_app')
21
-
22
- expect(status).to eql 401
23
- expect(headers).to eql('WWW-Authenticate' => 'Token realm="my_app"')
24
- expect(JSON.load(response[0])).to include(
25
- 'errors' => [
26
- include(
27
- 'id' => match(/[a-f0-9\-]+/),
28
- 'links' => {
29
- 'about' => nil,
30
- 'documentation' => nil,
31
- },
32
- 'status' => 401,
33
- 'code' => 'errors.invalid_token',
34
- 'title' => 'Invalid or Unauthorized Token',
35
- 'detail' => 'Either the token you passed is invalid or is not allowed to ' \
36
- 'perform this action.',
37
- 'source' => {},
38
- ),
39
- ],
40
- )
41
- end
42
- end
43
- end
44
- end
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/requests/base'
4
- require 'drillbit/matchers/accept_header'
5
-
6
- # rubocop:disable Metrics/LineLength
7
- module Drillbit
8
- module Matchers
9
- describe AcceptHeader do
10
- it 'matches if the subdomain is API and the accept header is valid' do
11
- env = {
12
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep;version=1.0.0',
13
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
14
- }
15
- request = Requests::Base.resolve(env)
16
-
17
- matcher = AcceptHeader.new
18
-
19
- expect(matcher.matches?(request)).to be_a TrueClass
20
- end
21
-
22
- it 'matches if the subdomain is API and the accept header is passed in as ' \
23
- 'a parameter' do
24
-
25
- env = {
26
- 'QUERY_STRING' => 'accept=application/vnd.westeros+redkeep;version=1.0.0',
27
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
28
- }
29
- request = Requests::Base.resolve(env)
30
-
31
- matcher = AcceptHeader.new
32
-
33
- expect(matcher.matches?(request)).to be_a TrueClass
34
- end
35
-
36
- it 'matches if the subdomain is API and the accept header is passed in as a ' \
37
- 'secondary parameter' do
38
-
39
- env = {
40
- 'QUERY_STRING' => 'first=my_param&accept=application/vnd.westeros+redkeep;' \
41
- 'version=1.0.0',
42
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
43
- }
44
- request = Requests::Base.resolve(env)
45
-
46
- matcher = AcceptHeader.new
47
-
48
- expect(matcher.matches?(request)).to be_a TrueClass
49
- end
50
-
51
- it 'matches the header accept header if the subdomain is API and the accept header ' \
52
- 'is passed both as a valid header and as a parameter' do
53
-
54
- env = {
55
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep;version=1.0.0',
56
- 'QUERY_STRING' => 'accept=application/vnd.westeros+redkeep;version=2.0.0',
57
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
58
- }
59
- request = Requests::Base.resolve(env)
60
-
61
- matcher = AcceptHeader.new
62
- matcher.matches?(request)
63
-
64
- expect(matcher.accept_header.version).to eql '1.0.0'
65
- end
66
-
67
- it 'matches the accept header parameter if the subdomain is API and the accept ' \
68
- 'header is passed both as an invalid header as well as as a parameter' do
69
-
70
- env = {
71
- 'HTTP_ACCEPT' => 'application/vndwesteros+redkeep;version=1.0.0',
72
- 'QUERY_STRING' => 'accept=application/vnd.westeros+redkeep;version=2.0.0',
73
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
74
- }
75
- request = Requests::Base.resolve(env)
76
-
77
- matcher = AcceptHeader.new
78
- matcher.matches?(request)
79
-
80
- expect(matcher.accept_header.version).to eql '2.0.0'
81
- end
82
-
83
- it 'matches the accept header parameter if the subdomain is API and the accept ' \
84
- 'header is passed both as an invalid header as well as as a parameter' do
85
-
86
- env = {
87
- 'HTTP_ACCEPT' => 'application/vndwesteros+redkeep;version=1.0.0',
88
- 'QUERY_STRING' => '',
89
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
90
- }
91
- request = Requests::Base.resolve(env)
92
-
93
- matcher = AcceptHeader.new
94
- matcher.matches?(request)
95
-
96
- expect(matcher.accept_header.raw_accept_header).to eql \
97
- 'application/vndwesteros+redkeep;version=1.0.0'
98
- end
99
-
100
- it 'does not match if the subdomain is API but the accept header is invalid' do
101
- env = {
102
- 'HTTP_ACCEPT' => 'application/vndwesteros+redkeep;version=1.0.0',
103
- 'QUERY_STRING' => '',
104
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
105
- }
106
- request = Requests::Base.resolve(env)
107
-
108
- matcher = AcceptHeader.new
109
-
110
- expect(matcher.matches?(request)).to be_a FalseClass
111
- end
112
- end
113
- end
114
- end