pact_broker 2.95.0 → 2.95.1
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/db.rb +1 -0
- data/lib/pact_broker/api/resources/base_resource.rb +273 -1
- data/lib/pact_broker/api/resources/default_base_resource.rb +0 -280
- data/lib/pact_broker/configuration.rb +1 -5
- data/lib/pact_broker/index/service.rb +1 -1
- data/lib/pact_broker/matrix/repository.rb +9 -9
- data/lib/pact_broker/pacts/pact_publication.rb +12 -6
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +10 -2
- data/lib/pact_broker/pacts/repository.rb +1 -0
- data/lib/pact_broker/repositories/helpers.rb +4 -0
- data/lib/pact_broker/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f65cf2bd6eb2b3f0f7fd727e61fc73005817200f8e72bbab574493e4ea9b9ba3
|
4
|
+
data.tar.gz: aac1fb501fc5624227e63d424c8982f266fa0a9a2d80b1184844193347ba6724
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8272759e5880069606e56bea3893055df49543b76b237d7511ce8fa21c0414f1a0e593e98ed1f9e67c4b9048b4da1c2d3ef938b0dfea182406cda696111c2bc4
|
7
|
+
data.tar.gz: 426a032f0016c8952934fbf630420be42accf192baeaff3bd2651aefa75170d055d8a4ed125640a7b3cad124cf5a461d7c930e5d289f4a6e5bd666366661940a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
<a name="v2.95.1"></a>
|
2
|
+
### v2.95.1 (2022-03-18)
|
3
|
+
|
4
|
+
#### Bug Fixes
|
5
|
+
|
6
|
+
* **can-i-deploy**
|
7
|
+
* allow new provider to be introduced to existing consumer without can-i-deploy having circular dependency issues ([e43974ca](/../../commit/e43974ca))
|
8
|
+
|
1
9
|
<a name="v2.95.0"></a>
|
2
10
|
### v2.95.0 (2022-03-16)
|
3
11
|
|
data/lib/db.rb
CHANGED
@@ -1,9 +1,281 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "pact_broker/configuration"
|
3
|
+
require "webmachine"
|
4
|
+
require "pact_broker/services"
|
5
|
+
require "pact_broker/api/decorators"
|
6
|
+
require "pact_broker/logging"
|
7
|
+
require "pact_broker/api/pact_broker_urls"
|
8
|
+
require "pact_broker/json"
|
9
|
+
require "pact_broker/pacts/pact_params"
|
10
|
+
require "pact_broker/api/resources/authentication"
|
11
|
+
require "pact_broker/api/resources/authorization"
|
12
|
+
require "pact_broker/errors"
|
2
13
|
|
3
14
|
module PactBroker
|
4
15
|
module Api
|
5
16
|
module Resources
|
6
|
-
|
17
|
+
class InvalidJsonError < PactBroker::Error ; end
|
18
|
+
|
19
|
+
class BaseResource < Webmachine::Resource
|
20
|
+
include PactBroker::Services
|
21
|
+
include PactBroker::Api::PactBrokerUrls
|
22
|
+
include PactBroker::Api::Resources::Authentication
|
23
|
+
include PactBroker::Api::Resources::Authorization
|
24
|
+
|
25
|
+
include PactBroker::Logging
|
26
|
+
|
27
|
+
attr_accessor :user
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
PactBroker.configuration.before_resource.call(self)
|
31
|
+
application_context.before_resource&.call(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def options
|
35
|
+
{ "Access-Control-Allow-Methods" => allowed_methods.join(", ")}
|
36
|
+
end
|
37
|
+
|
38
|
+
def known_methods
|
39
|
+
super + ["PATCH"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def finish_request
|
43
|
+
application_context.after_resource&.call(self)
|
44
|
+
PactBroker.configuration.after_resource.call(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_authorized?(authorization_header)
|
48
|
+
authenticated?(self, authorization_header)
|
49
|
+
end
|
50
|
+
|
51
|
+
def forbidden?
|
52
|
+
if application_context.resource_authorizer
|
53
|
+
!application_context.resource_authorizer.call(self)
|
54
|
+
elsif PactBroker.configuration.authorize
|
55
|
+
!PactBroker.configuration.authorize.call(self, {})
|
56
|
+
else
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# The path_info segments aren't URL decoded
|
62
|
+
def identifier_from_path
|
63
|
+
@identifier_from_path ||= request.path_info.each_with_object({}) do | (key, value), hash|
|
64
|
+
if value.is_a?(String)
|
65
|
+
hash[key] = URI.decode(value)
|
66
|
+
elsif value.is_a?(Symbol) || value.is_a?(Numeric)
|
67
|
+
hash[key] = value
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
alias_method :path_info, :identifier_from_path
|
73
|
+
|
74
|
+
def base_url
|
75
|
+
# Have to use something for the base URL here - we can't use an empty string as we can in the UI.
|
76
|
+
# Can't work out if cache poisoning is a vulnerability for APIs or not.
|
77
|
+
# Using the request base URI as a fallback if the base_url is not configured may be a vulnerability,
|
78
|
+
# but the documentation recommends that the
|
79
|
+
# base_url should be set in the configuration to mitigate this.
|
80
|
+
request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp("/")
|
81
|
+
end
|
82
|
+
|
83
|
+
# See comments for base_url in lib/pact_broker/doc/controllers/app.rb
|
84
|
+
def ui_base_url
|
85
|
+
request.env["pactbroker.base_url"] || ""
|
86
|
+
end
|
87
|
+
|
88
|
+
def charsets_provided
|
89
|
+
[["utf-8", :encode]]
|
90
|
+
end
|
91
|
+
|
92
|
+
# We only use utf-8 so leave encoding as it is
|
93
|
+
def encode(body)
|
94
|
+
body
|
95
|
+
end
|
96
|
+
|
97
|
+
def resource_url
|
98
|
+
request.uri.to_s.gsub(/\?.*/, "").chomp("/")
|
99
|
+
end
|
100
|
+
|
101
|
+
def decorator_context options = {}
|
102
|
+
application_context.decorator_context_creator.call(self, options)
|
103
|
+
end
|
104
|
+
|
105
|
+
def decorator_options options = {}
|
106
|
+
{ user_options: decorator_context(options) }
|
107
|
+
end
|
108
|
+
|
109
|
+
def handle_exception(error)
|
110
|
+
error_reference = PactBroker::Errors.generate_error_reference
|
111
|
+
application_context.error_logger.call(error, error_reference, request.env)
|
112
|
+
if PactBroker::Errors.reportable_error?(error)
|
113
|
+
PactBroker::Errors.report(error, error_reference, request.env)
|
114
|
+
end
|
115
|
+
response.body = application_context.error_response_body_generator.call(error, error_reference, request.env)
|
116
|
+
end
|
117
|
+
|
118
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
119
|
+
def params(options = {})
|
120
|
+
return options[:default] if options.key?(:default) && request_body.empty?
|
121
|
+
|
122
|
+
symbolize_names = !options.key?(:symbolize_names) || options[:symbolize_names]
|
123
|
+
if symbolize_names
|
124
|
+
@params_with_symbol_keys ||= JSON.parse(request_body, { symbolize_names: true }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
|
125
|
+
else
|
126
|
+
@params_with_string_keys ||= JSON.parse(request_body, { symbolize_names: false }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
|
127
|
+
end
|
128
|
+
rescue JSON::JSONError => e
|
129
|
+
raise InvalidJsonError.new("Error parsing JSON - #{e.message}")
|
130
|
+
end
|
131
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
132
|
+
|
133
|
+
def params_with_string_keys
|
134
|
+
params(symbolize_names: false)
|
135
|
+
end
|
136
|
+
|
137
|
+
def pact_params
|
138
|
+
@pact_params ||= PactBroker::Pacts::PactParams.from_request request, identifier_from_path
|
139
|
+
end
|
140
|
+
|
141
|
+
def set_json_error_message message
|
142
|
+
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
143
|
+
response.body = { error: message }.to_json
|
144
|
+
end
|
145
|
+
|
146
|
+
def set_json_validation_error_messages errors
|
147
|
+
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
148
|
+
response.body = { errors: errors }.to_json
|
149
|
+
end
|
150
|
+
|
151
|
+
def request_body
|
152
|
+
@request_body ||= request.body.to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
def consumer_name
|
156
|
+
identifier_from_path[:consumer_name]
|
157
|
+
end
|
158
|
+
|
159
|
+
def consumer_version_number
|
160
|
+
identifier_from_path[:consumer_version_number]
|
161
|
+
end
|
162
|
+
|
163
|
+
def pacticipant_version_number
|
164
|
+
identifier_from_path[:pacticipant_version_number]
|
165
|
+
end
|
166
|
+
|
167
|
+
def consumer_specified?
|
168
|
+
identifier_from_path.key?(:consumer_name)
|
169
|
+
end
|
170
|
+
|
171
|
+
def provider_specified?
|
172
|
+
identifier_from_path.key?(:provider_name)
|
173
|
+
end
|
174
|
+
|
175
|
+
def provider_name
|
176
|
+
identifier_from_path[:provider_name]
|
177
|
+
end
|
178
|
+
|
179
|
+
def pacticipant_name
|
180
|
+
identifier_from_path[:pacticipant_name]
|
181
|
+
end
|
182
|
+
|
183
|
+
def pacticipant_specified?
|
184
|
+
identifier_from_path.key?(:pacticipant_name)
|
185
|
+
end
|
186
|
+
|
187
|
+
def invalid_json?
|
188
|
+
begin
|
189
|
+
params
|
190
|
+
false
|
191
|
+
rescue StandardError => e
|
192
|
+
logger.info "Error parsing JSON #{e} - #{request_body}"
|
193
|
+
set_json_error_message "Error parsing JSON - #{e.message}"
|
194
|
+
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
195
|
+
true
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def validation_errors? model
|
200
|
+
if (errors = model.validate).any?
|
201
|
+
set_json_validation_error_messages errors
|
202
|
+
true
|
203
|
+
else
|
204
|
+
false
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def contract_validation_errors? contract, params
|
209
|
+
if (invalid = !contract.validate(params))
|
210
|
+
set_json_validation_error_messages contract.errors.messages
|
211
|
+
end
|
212
|
+
invalid
|
213
|
+
end
|
214
|
+
|
215
|
+
def find_pacticipant name, role
|
216
|
+
pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
|
217
|
+
set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def consumer
|
222
|
+
@consumer ||= identifier_from_path[:consumer_name] && find_pacticipant(identifier_from_path[:consumer_name], "consumer")
|
223
|
+
end
|
224
|
+
|
225
|
+
def provider
|
226
|
+
@provider ||= identifier_from_path[:provider_name] && find_pacticipant(identifier_from_path[:provider_name], "provider")
|
227
|
+
end
|
228
|
+
|
229
|
+
def pacticipant
|
230
|
+
@pacticipant ||= identifier_from_path[:pacticipant_name] && find_pacticipant(identifier_from_path[:pacticipant_name], "pacticipant")
|
231
|
+
end
|
232
|
+
|
233
|
+
def pact
|
234
|
+
@pact ||= pact_service.find_pact(pact_params)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Not necessarily an existing integration
|
238
|
+
def integration
|
239
|
+
if consumer_specified? && provider_specified?
|
240
|
+
OpenStruct.new(consumer: consumer, provider: provider)
|
241
|
+
else
|
242
|
+
nil
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def database_connector
|
247
|
+
request.env["pactbroker.database_connector"]
|
248
|
+
end
|
249
|
+
|
250
|
+
def application_context
|
251
|
+
request.path_info[:application_context]
|
252
|
+
end
|
253
|
+
|
254
|
+
def decorator_class(name)
|
255
|
+
application_context.decorator_configuration.class_for(name)
|
256
|
+
end
|
257
|
+
|
258
|
+
def api_contract_class(name)
|
259
|
+
application_context.api_contract_configuration.class_for(name)
|
260
|
+
end
|
261
|
+
|
262
|
+
def schema
|
263
|
+
nil
|
264
|
+
end
|
265
|
+
|
266
|
+
def validation_errors_for_schema?(schema_to_use = schema, params_to_validate = params)
|
267
|
+
if (errors = schema_to_use.call(params_to_validate)).any?
|
268
|
+
set_json_validation_error_messages(errors)
|
269
|
+
true
|
270
|
+
else
|
271
|
+
false
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def malformed_request_for_json_with_schema?(schema_to_use = schema, params_to_validate = params)
|
276
|
+
invalid_json? || validation_errors_for_schema?(schema_to_use, params_to_validate)
|
277
|
+
end
|
278
|
+
end
|
7
279
|
end
|
8
280
|
end
|
9
281
|
end
|
@@ -1,280 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "webmachine"
|
3
|
-
require "pact_broker/services"
|
4
|
-
require "pact_broker/api/decorators"
|
5
|
-
require "pact_broker/logging"
|
6
|
-
require "pact_broker/api/pact_broker_urls"
|
7
|
-
require "pact_broker/json"
|
8
|
-
require "pact_broker/pacts/pact_params"
|
9
|
-
require "pact_broker/api/resources/authentication"
|
10
|
-
require "pact_broker/api/resources/authorization"
|
11
|
-
require "pact_broker/errors"
|
12
|
-
|
13
|
-
module PactBroker
|
14
|
-
module Api
|
15
|
-
module Resources
|
16
|
-
class InvalidJsonError < PactBroker::Error ; end
|
17
|
-
|
18
|
-
class DefaultBaseResource < Webmachine::Resource
|
19
|
-
include PactBroker::Services
|
20
|
-
include PactBroker::Api::PactBrokerUrls
|
21
|
-
include PactBroker::Api::Resources::Authentication
|
22
|
-
include PactBroker::Api::Resources::Authorization
|
23
|
-
|
24
|
-
include PactBroker::Logging
|
25
|
-
|
26
|
-
attr_accessor :user
|
27
|
-
|
28
|
-
def initialize
|
29
|
-
PactBroker.configuration.before_resource.call(self)
|
30
|
-
application_context.before_resource&.call(self)
|
31
|
-
end
|
32
|
-
|
33
|
-
def options
|
34
|
-
{ "Access-Control-Allow-Methods" => allowed_methods.join(", ")}
|
35
|
-
end
|
36
|
-
|
37
|
-
def known_methods
|
38
|
-
super + ["PATCH"]
|
39
|
-
end
|
40
|
-
|
41
|
-
def finish_request
|
42
|
-
application_context.after_resource&.call(self)
|
43
|
-
PactBroker.configuration.after_resource.call(self)
|
44
|
-
end
|
45
|
-
|
46
|
-
def is_authorized?(authorization_header)
|
47
|
-
authenticated?(self, authorization_header)
|
48
|
-
end
|
49
|
-
|
50
|
-
def forbidden?
|
51
|
-
if application_context.resource_authorizer
|
52
|
-
!application_context.resource_authorizer.call(self)
|
53
|
-
elsif PactBroker.configuration.authorize
|
54
|
-
!PactBroker.configuration.authorize.call(self, {})
|
55
|
-
else
|
56
|
-
false
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# The path_info segments aren't URL decoded
|
61
|
-
def identifier_from_path
|
62
|
-
@identifier_from_path ||= request.path_info.each_with_object({}) do | (key, value), hash|
|
63
|
-
if value.is_a?(String)
|
64
|
-
hash[key] = URI.decode(value)
|
65
|
-
elsif value.is_a?(Symbol) || value.is_a?(Numeric)
|
66
|
-
hash[key] = value
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
alias_method :path_info, :identifier_from_path
|
72
|
-
|
73
|
-
def base_url
|
74
|
-
# Have to use something for the base URL here - we can't use an empty string as we can in the UI.
|
75
|
-
# Can't work out if cache poisoning is a vulnerability for APIs or not.
|
76
|
-
# Using the request base URI as a fallback if the base_url is not configured may be a vulnerability,
|
77
|
-
# but the documentation recommends that the
|
78
|
-
# base_url should be set in the configuration to mitigate this.
|
79
|
-
request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp("/")
|
80
|
-
end
|
81
|
-
|
82
|
-
# See comments for base_url in lib/pact_broker/doc/controllers/app.rb
|
83
|
-
def ui_base_url
|
84
|
-
request.env["pactbroker.base_url"] || ""
|
85
|
-
end
|
86
|
-
|
87
|
-
def charsets_provided
|
88
|
-
[["utf-8", :encode]]
|
89
|
-
end
|
90
|
-
|
91
|
-
# We only use utf-8 so leave encoding as it is
|
92
|
-
def encode(body)
|
93
|
-
body
|
94
|
-
end
|
95
|
-
|
96
|
-
def resource_url
|
97
|
-
request.uri.to_s.gsub(/\?.*/, "").chomp("/")
|
98
|
-
end
|
99
|
-
|
100
|
-
def decorator_context options = {}
|
101
|
-
application_context.decorator_context_creator.call(self, options)
|
102
|
-
end
|
103
|
-
|
104
|
-
def decorator_options options = {}
|
105
|
-
{ user_options: decorator_context(options) }
|
106
|
-
end
|
107
|
-
|
108
|
-
def handle_exception(error)
|
109
|
-
error_reference = PactBroker::Errors.generate_error_reference
|
110
|
-
application_context.error_logger.call(error, error_reference, request.env)
|
111
|
-
if PactBroker::Errors.reportable_error?(error)
|
112
|
-
PactBroker::Errors.report(error, error_reference, request.env)
|
113
|
-
end
|
114
|
-
response.body = application_context.error_response_body_generator.call(error, error_reference, request.env)
|
115
|
-
end
|
116
|
-
|
117
|
-
# rubocop: disable Metrics/CyclomaticComplexity
|
118
|
-
def params(options = {})
|
119
|
-
return options[:default] if options.key?(:default) && request_body.empty?
|
120
|
-
|
121
|
-
symbolize_names = !options.key?(:symbolize_names) || options[:symbolize_names]
|
122
|
-
if symbolize_names
|
123
|
-
@params_with_symbol_keys ||= JSON.parse(request_body, { symbolize_names: true }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
|
124
|
-
else
|
125
|
-
@params_with_string_keys ||= JSON.parse(request_body, { symbolize_names: false }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
|
126
|
-
end
|
127
|
-
rescue JSON::JSONError => e
|
128
|
-
raise InvalidJsonError.new("Error parsing JSON - #{e.message}")
|
129
|
-
end
|
130
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
131
|
-
|
132
|
-
def params_with_string_keys
|
133
|
-
params(symbolize_names: false)
|
134
|
-
end
|
135
|
-
|
136
|
-
def pact_params
|
137
|
-
@pact_params ||= PactBroker::Pacts::PactParams.from_request request, identifier_from_path
|
138
|
-
end
|
139
|
-
|
140
|
-
def set_json_error_message message
|
141
|
-
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
142
|
-
response.body = { error: message }.to_json
|
143
|
-
end
|
144
|
-
|
145
|
-
def set_json_validation_error_messages errors
|
146
|
-
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
147
|
-
response.body = { errors: errors }.to_json
|
148
|
-
end
|
149
|
-
|
150
|
-
def request_body
|
151
|
-
@request_body ||= request.body.to_s
|
152
|
-
end
|
153
|
-
|
154
|
-
def consumer_name
|
155
|
-
identifier_from_path[:consumer_name]
|
156
|
-
end
|
157
|
-
|
158
|
-
def consumer_version_number
|
159
|
-
identifier_from_path[:consumer_version_number]
|
160
|
-
end
|
161
|
-
|
162
|
-
def pacticipant_version_number
|
163
|
-
identifier_from_path[:pacticipant_version_number]
|
164
|
-
end
|
165
|
-
|
166
|
-
def consumer_specified?
|
167
|
-
identifier_from_path.key?(:consumer_name)
|
168
|
-
end
|
169
|
-
|
170
|
-
def provider_specified?
|
171
|
-
identifier_from_path.key?(:provider_name)
|
172
|
-
end
|
173
|
-
|
174
|
-
def provider_name
|
175
|
-
identifier_from_path[:provider_name]
|
176
|
-
end
|
177
|
-
|
178
|
-
def pacticipant_name
|
179
|
-
identifier_from_path[:pacticipant_name]
|
180
|
-
end
|
181
|
-
|
182
|
-
def pacticipant_specified?
|
183
|
-
identifier_from_path.key?(:pacticipant_name)
|
184
|
-
end
|
185
|
-
|
186
|
-
def invalid_json?
|
187
|
-
begin
|
188
|
-
params
|
189
|
-
false
|
190
|
-
rescue StandardError => e
|
191
|
-
logger.info "Error parsing JSON #{e} - #{request_body}"
|
192
|
-
set_json_error_message "Error parsing JSON - #{e.message}"
|
193
|
-
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
194
|
-
true
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def validation_errors? model
|
199
|
-
if (errors = model.validate).any?
|
200
|
-
set_json_validation_error_messages errors
|
201
|
-
true
|
202
|
-
else
|
203
|
-
false
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def contract_validation_errors? contract, params
|
208
|
-
if (invalid = !contract.validate(params))
|
209
|
-
set_json_validation_error_messages contract.errors.messages
|
210
|
-
end
|
211
|
-
invalid
|
212
|
-
end
|
213
|
-
|
214
|
-
def find_pacticipant name, role
|
215
|
-
pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
|
216
|
-
set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def consumer
|
221
|
-
@consumer ||= identifier_from_path[:consumer_name] && find_pacticipant(identifier_from_path[:consumer_name], "consumer")
|
222
|
-
end
|
223
|
-
|
224
|
-
def provider
|
225
|
-
@provider ||= identifier_from_path[:provider_name] && find_pacticipant(identifier_from_path[:provider_name], "provider")
|
226
|
-
end
|
227
|
-
|
228
|
-
def pacticipant
|
229
|
-
@pacticipant ||= identifier_from_path[:pacticipant_name] && find_pacticipant(identifier_from_path[:pacticipant_name], "pacticipant")
|
230
|
-
end
|
231
|
-
|
232
|
-
def pact
|
233
|
-
@pact ||= pact_service.find_pact(pact_params)
|
234
|
-
end
|
235
|
-
|
236
|
-
# Not necessarily an existing integration
|
237
|
-
def integration
|
238
|
-
if consumer_specified? && provider_specified?
|
239
|
-
OpenStruct.new(consumer: consumer, provider: provider)
|
240
|
-
else
|
241
|
-
nil
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
def database_connector
|
246
|
-
request.env["pactbroker.database_connector"]
|
247
|
-
end
|
248
|
-
|
249
|
-
def application_context
|
250
|
-
request.path_info[:application_context]
|
251
|
-
end
|
252
|
-
|
253
|
-
def decorator_class(name)
|
254
|
-
application_context.decorator_configuration.class_for(name)
|
255
|
-
end
|
256
|
-
|
257
|
-
def api_contract_class(name)
|
258
|
-
application_context.api_contract_configuration.class_for(name)
|
259
|
-
end
|
260
|
-
|
261
|
-
def schema
|
262
|
-
nil
|
263
|
-
end
|
264
|
-
|
265
|
-
def validation_errors_for_schema?(schema_to_use = schema, params_to_validate = params)
|
266
|
-
if (errors = schema_to_use.call(params_to_validate)).any?
|
267
|
-
set_json_validation_error_messages(errors)
|
268
|
-
true
|
269
|
-
else
|
270
|
-
false
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
def malformed_request_for_json_with_schema?(schema_to_use = schema, params_to_validate = params)
|
275
|
-
invalid_json? || validation_errors_for_schema?(schema_to_use, params_to_validate)
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
@@ -35,7 +35,7 @@ module PactBroker
|
|
35
35
|
attr_accessor :content_security_policy, :hal_browser_content_security_policy_overrides
|
36
36
|
attr_accessor :api_error_reporters
|
37
37
|
attr_reader :custom_logger
|
38
|
-
attr_accessor :policy_builder, :policy_scope_builder
|
38
|
+
attr_accessor :policy_builder, :policy_scope_builder
|
39
39
|
alias_method :policy_finder=, :policy_builder=
|
40
40
|
alias_method :policy_scope_finder=, :policy_scope_builder=
|
41
41
|
|
@@ -79,10 +79,6 @@ module PactBroker
|
|
79
79
|
}
|
80
80
|
config.policy_builder = -> (object) { DefaultPolicy.new(nil, object) }
|
81
81
|
config.policy_scope_builder = -> (scope) { scope }
|
82
|
-
config.base_resource_class_factory = -> () {
|
83
|
-
require "pact_broker/api/resources/default_base_resource"
|
84
|
-
PactBroker::Api::Resources::DefaultBaseResource
|
85
|
-
}
|
86
82
|
config
|
87
83
|
end
|
88
84
|
|
@@ -108,7 +108,7 @@ module PactBroker
|
|
108
108
|
# rubocop: disable Metrics/CyclomaticComplexity
|
109
109
|
def self.latest_verification_for_pseudo_branch(pact_publication, is_overall_latest, latest_verifications_for_cv_tags, tags_option, options)
|
110
110
|
if options[:view] == "branch" || (options[:view] == "all" && pact_publication.consumer_version.branch_heads.any?)
|
111
|
-
pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches
|
111
|
+
pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches(forbid_lazy_load: false)
|
112
112
|
elsif tags_option == true
|
113
113
|
latest_verifications_for_cv_tags
|
114
114
|
.select{ | v | v.consumer_id == pact_publication.consumer_id && v.provider_id == pact_publication.provider_id && pact_publication.head_pact_tags.collect(&:name).include?(v.consumer_version_tag_name) }
|
@@ -84,7 +84,7 @@ module PactBroker
|
|
84
84
|
|
85
85
|
def find_integrations_for_specified_selectors(resolved_specified_selectors, options)
|
86
86
|
if infer_selectors_for_integrations?(options)
|
87
|
-
find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors
|
87
|
+
find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors)
|
88
88
|
else
|
89
89
|
find_integrations_for_specified_selectors_only(resolved_specified_selectors)
|
90
90
|
end
|
@@ -101,9 +101,9 @@ module PactBroker
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
def find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors
|
104
|
+
def find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors)
|
105
105
|
integrations = integrations_where_specified_selector_is_consumer(resolved_specified_selectors) +
|
106
|
-
integrations_where_specified_selector_is_provider(resolved_specified_selectors
|
106
|
+
integrations_where_specified_selector_is_provider(resolved_specified_selectors)
|
107
107
|
deduplicate_integrations(integrations)
|
108
108
|
end
|
109
109
|
|
@@ -118,28 +118,25 @@ module PactBroker
|
|
118
118
|
consumer_name: integration[:consumer_name],
|
119
119
|
provider_id: integration[:provider_id],
|
120
120
|
provider_name: integration[:provider_name],
|
121
|
-
required: true
|
121
|
+
required: true # synchronous consumer requires the provider to be present
|
122
122
|
)
|
123
123
|
end
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
def integrations_where_specified_selector_is_provider(resolved_specified_selectors
|
127
|
+
def integrations_where_specified_selector_is_provider(resolved_specified_selectors)
|
128
128
|
integrations_involving_specified_providers = PactBroker::Integrations::Integration
|
129
129
|
.where(provider_id: resolved_specified_selectors.collect(&:pacticipant_id))
|
130
130
|
.eager(:consumer, :provider)
|
131
131
|
.all
|
132
132
|
|
133
|
-
destination_selector = PactBroker::Matrix::UnresolvedSelector.new(options.slice(:latest, :tag, :branch, :environment_name).compact)
|
134
|
-
required = PactBroker::Domain::Version.for_selector(destination_selector).pacticipants_set
|
135
|
-
|
136
133
|
integrations_involving_specified_providers.collect do | integration |
|
137
134
|
Integration.from_hash(
|
138
135
|
consumer_id: integration.consumer.id,
|
139
136
|
consumer_name: integration.consumer.name,
|
140
137
|
provider_id: integration.provider.id,
|
141
138
|
provider_name: integration.provider.name,
|
142
|
-
required:
|
139
|
+
required: false # synchronous provider does not require the consumer to be present
|
143
140
|
)
|
144
141
|
end
|
145
142
|
end
|
@@ -263,6 +260,9 @@ module PactBroker
|
|
263
260
|
end
|
264
261
|
end
|
265
262
|
|
263
|
+
# The user has specified --to TAG or --to-environment ENVIRONMENT in the CLI
|
264
|
+
# (or nothing, which to defaults to "with the latest version of the other integrated applications")
|
265
|
+
# The branch isn't implemented in the CLI yet (March 2022), but the API supports it.
|
266
266
|
def infer_selectors_for_integrations?(options)
|
267
267
|
options[:latest] || options[:tag] || options[:branch] || options[:environment_name]
|
268
268
|
end
|
@@ -20,11 +20,11 @@ module PactBroker
|
|
20
20
|
delegate [:consumer_version_number, :name, :provider_name, :consumer_name] => :cached_domain_for_delegation
|
21
21
|
|
22
22
|
set_primary_key :id
|
23
|
-
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
|
24
|
-
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
|
25
|
-
associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id)
|
26
|
-
associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id)
|
27
|
-
associate(:many_to_one, :integration, class: "PactBroker::Integrations::Integration", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id])
|
23
|
+
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id, forbid_lazy_load: false)
|
24
|
+
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id, forbid_lazy_load: false)
|
25
|
+
associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id, forbid_lazy_load: false)
|
26
|
+
associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id, forbid_lazy_load: false)
|
27
|
+
associate(:many_to_one, :integration, class: "PactBroker::Integrations::Integration", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id], forbid_lazy_load: false)
|
28
28
|
|
29
29
|
# TODO rename to consumer_version_tags
|
30
30
|
associate(:one_to_many, :tags, :class => "PactBroker::Domain::Tag", :key => :version_id, :primary_key => :consumer_version_id)
|
@@ -105,8 +105,14 @@ module PactBroker
|
|
105
105
|
.collect { | head_pact_publication| head_pact_publication.values.fetch(:tag_name) }
|
106
106
|
end
|
107
107
|
|
108
|
+
# If the consumer_version is already loaded, and it already has tags, use those
|
109
|
+
# otherwise, load them directly.
|
108
110
|
def consumer_version_tags
|
109
|
-
tags
|
111
|
+
if associations[:consumer_version] && associations[:consumer_version].associations[:tags]
|
112
|
+
consumer_version.tags
|
113
|
+
else
|
114
|
+
tags
|
115
|
+
end
|
110
116
|
end
|
111
117
|
|
112
118
|
def latest_verification
|
@@ -299,7 +299,15 @@ module PactBroker
|
|
299
299
|
end
|
300
300
|
|
301
301
|
def collect_consumer_name_and_version_number(pact_publications_query)
|
302
|
-
|
302
|
+
pact_publications = pact_publications_query
|
303
|
+
.eager(:provider)
|
304
|
+
.eager(:consumer)
|
305
|
+
.eager(:consumer_version)
|
306
|
+
.order(:consumer_version_order)
|
307
|
+
.all_forbidding_lazy_load
|
308
|
+
.sort
|
309
|
+
|
310
|
+
pact_publications.collect do |p|
|
303
311
|
suffix = if p.values[:tag_name]
|
304
312
|
" (tag #{p.values[:tag_name]})"
|
305
313
|
elsif p.values[:branch_name]
|
@@ -308,7 +316,7 @@ module PactBroker
|
|
308
316
|
""
|
309
317
|
end
|
310
318
|
|
311
|
-
"#{p.
|
319
|
+
"#{p.consumer.name} #{p.consumer_version.number}" + suffix
|
312
320
|
end
|
313
321
|
end
|
314
322
|
|
@@ -257,6 +257,7 @@ module PactBroker
|
|
257
257
|
.collect(&:to_domain_with_content).first
|
258
258
|
elsif consumer_version_number && pact_version_sha
|
259
259
|
pact_publication = pact_publication_by_consumer_version.all.first
|
260
|
+
pact_publication&.allow_lazy_load
|
260
261
|
if pact_publication && pact_publication.pact_version.sha == pact_version_sha
|
261
262
|
pact_publication.tags
|
262
263
|
pact_publication.to_domain_with_content
|
@@ -6,6 +6,10 @@ module PactBroker
|
|
6
6
|
|
7
7
|
extend self
|
8
8
|
|
9
|
+
def all_forbidding_lazy_load
|
10
|
+
all.each{ | row | row.forbid_lazy_load if row.respond_to?(:forbid_lazy_load) }
|
11
|
+
end
|
12
|
+
|
9
13
|
def name_like column_name, value
|
10
14
|
if PactBroker.configuration.use_case_sensitive_resource_names
|
11
15
|
if mysql?
|
data/lib/pact_broker/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact_broker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.95.
|
4
|
+
version: 2.95.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bethany Skurrie
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-03-
|
13
|
+
date: 2022-03-21 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: httparty
|