Class: PactBroker::Api::Resources::BaseResource
Direct Known Subclasses
AllWebhooks, Badge, Branch, BranchVersion, BranchVersions, CanIDeployPacticipantVersionByBranchToEnvironment, CanIMergeBadge, Clean, CurrentlyDeployedVersionsForEnvironment, CurrentlySupportedVersionsForEnvironment, Dashboard, DeployedVersion, DeployedVersionsForVersionAndEnvironment, Environment, Environments, ErrorTest, Group, Index, Integration, Integrations, Label, Labels, LatestPact, LatestPacts, LatestVerificationsForConsumerVersion, Matrix, MatrixForConsumerAndProvider, Metrics, Pact, PactContentDiff, PactTriggeredWebhooks, PactVersions, PactVersionsForBranch, PactWebhooks, PactWebhooksStatus, Pacticipant, PacticipantBranches, PacticipantWebhooks, Pacticipants, PacticipantsForLabel, PreviousDistinctPactVersion, ProviderPacts, PublishContracts, Relationships, ReleasedVersion, ReleasedVersionsForVersionAndEnvironment, Tag, TaggedPactVersions, TriggeredWebhookLogs, Verification, VerificationTriggeredWebhooks, Verifications, Version, Versions, Webhook, WebhookExecution
Constant Summary
Pacts::Metadata::MAPPINGS
Constants included
from Services
Services::SERVICE_FACTORIES
Instance Attribute Summary collapse
Instance Method Summary
collapse
Methods included from Logging
included, #log_error, #log_with_tag, #measure_info
Methods included from Messages
#message, #pluralize, #validation_message, #validation_message_at_index
#fragment_before_invalid_utf_8_char
#decorator_options_for_error, #error_response_body, #error_response_content_type, #handle_exception, #log_and_report_error, #problem_json_error_content_type?, #set_json_error_message, #set_json_validation_error_messages, #validation_errors_decorator_class, #validation_errors_response_body
#action, #create_methods, #delete_methods, #read_methods, #update_methods
#authenticated?
#append_query_if_present, #badge_url_for_latest_pact, #branch_url, #branch_version_url, #branch_versions_url, #consumer_webhooks_url, #currently_deployed_versions_for_environment_url, #currently_supported_versions_for_environment_url, #dashboard_url_for_integration, #decode_pact_metadata, #deployed_version_url, #deployed_versions_for_version_and_environment_url, #encode_metadata, #environment_url, #environments_url, #group_url, #hal_browser_url, #integration_url, #label_url, #labels_url, #latest_pact_url, #latest_pacts_url, #latest_tagged_pact_url, #latest_untagged_pact_url, #latest_verification_for_pact_url, #latest_verifications_for_consumer_version_url, #latest_version_for_branch_url, #latest_version_url, #matrix_badge_url_for_selectors, #matrix_for_pact_url, #matrix_for_pacticipant_version_url, #matrix_url, #matrix_url_from_params, #new_verification_url, #pact_triggered_webhooks_url, #pact_url, #pact_url_from_params, #pact_version_url, #pact_version_url_with_metadata, #pact_version_url_with_webhook_metadata, #pact_version_with_consumer_version_metadata_url, #pact_versions_for_branch_url, #pact_versions_url, #pacticipant_branches_url, #pacticipant_url, #pacticipant_url_from_params, #pacticipants_url, #pacticipants_with_label_url, #previous_distinct_diff_url, #previous_distinct_pact_version_url, #provider_webhooks_url, #record_undeployment_url, #released_version_url, #released_versions_for_version_and_environment_url, #tag_url, #tagged_pact_versions_url, #tags_url, #templated_branch_version_url_for_pacticipant, #templated_can_i_deploy_badge_url, #templated_can_i_deploy_branch_to_environment_badge_url, #templated_can_i_deploy_url, #templated_diff_url, #templated_label_url_for_pacticipant, #templated_tag_url_for_pacticipant, #templated_version_url_for_pacticipant, #triggered_webhook_logs_url, #url_encode, #verification_publication_url, #verification_triggered_webhooks_url, #verification_url, #verification_url_from_params, #version_url, #version_url_from_params, #versions_url, #webhook_execution_url, #webhook_url, #webhooks_for_consumer_and_provider_url, #webhooks_for_pact_url, #webhooks_status_url, #webhooks_url
#build_metadata_for_consumer_version_number, #build_metadata_for_latest_pact, #build_metadata_for_pact_for_verification, #build_metadata_for_webhook_triggered_by_pact_publication, #parse_hash, #parse_metadata, #parse_object
Methods included from Services
#badge_service, #branch_service, #certificate_service, #contract_service, #deployed_version_service, #environment_service, #get_service, #group_service, #index_service, #integration_service, #label_service, #matrix_service, #metrics_service, #pact_service, #pacticipant_service, #register_default_services, #register_service, #released_version_service, #tag_service, #verification_service, #version_service, #webhook_service, #webhook_trigger_service
Constructor Details
Returns a new instance of BaseResource.
35
36
37
38
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 35
def initialize
PactBroker.configuration.before_resource.call(self)
application_context.before_resource&.call(self)
end
|
Instance Attribute Details
#user ⇒ Object
Returns the value of attribute user.
33
34
35
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 33
def user
@user
end
|
Instance Method Details
#any_request_body? ⇒ Boolean
151
152
153
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 151
def any_request_body?
request_body && request_body.size > 0
end
|
#api_contract_class(name) ⇒ Object
252
253
254
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 252
def api_contract_class(name)
application_context.api_contract_configuration.class_for(name)
end
|
#application_context ⇒ Object
244
245
246
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 244
def application_context
request.path_info[:application_context]
end
|
#base_url ⇒ Object
83
84
85
86
87
88
89
90
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 83
def base_url
request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp("/")
end
|
#charsets_provided ⇒ Object
97
98
99
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 97
def charsets_provided
[["utf-8", :encode]]
end
|
#consumer ⇒ Object
215
216
217
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 215
def consumer
@consumer ||= identifier_from_path[:consumer_name] && find_pacticipant(identifier_from_path[:consumer_name], "consumer")
end
|
#consumer_name ⇒ Object
155
156
157
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 155
def consumer_name
identifier_from_path[:consumer_name]
end
|
#consumer_specified? ⇒ Boolean
167
168
169
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 167
def consumer_specified?
identifier_from_path.key?(:consumer_name)
end
|
#consumer_version_number ⇒ Object
159
160
161
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 159
def consumer_version_number
identifier_from_path[:consumer_version_number]
end
|
#content_type_is_json_but_invalid_json_provided? ⇒ Boolean
Ensure we have valid JSON if a JSON body is required OR if a body has been provided
275
276
277
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 275
def content_type_is_json_but_invalid_json_provided?
content_type_json? && ((request_body_required? || any_request_body?) && invalid_json?)
end
|
#content_type_json? ⇒ Boolean
279
280
281
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 279
def content_type_json?
request.content_type&.include?("json")
end
|
#database_connector ⇒ Object
240
241
242
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 240
def database_connector
request.env["pactbroker.database_connector"]
end
|
#decorator_class(name) ⇒ Object
248
249
250
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 248
def decorator_class(name)
application_context.decorator_configuration.class_for(name)
end
|
#decorator_context(options = {}) ⇒ Object
110
111
112
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 110
def decorator_context options = {}
application_context.decorator_context_creator.call(self, options)
end
|
#decorator_options(options = {}) ⇒ Object
114
115
116
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 114
def decorator_options options = {}
{ user_options: decorator_context(options) }
end
|
#encode(body) ⇒ Object
We only use utf-8 so leave encoding as it is
102
103
104
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 102
def encode(body)
body
end
|
#find_pacticipant(name, role) ⇒ Object
207
208
209
210
211
212
213
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 207
def find_pacticipant name, role
pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
if pacticipant.nil?
set_json_error_message("No #{role} with name '#{name}' found", title: "Not found", type: "not-found", status: 404)
end
end
end
|
#finish_request ⇒ Object
52
53
54
55
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 52
def finish_request
application_context.after_resource&.call(self)
PactBroker.configuration.after_resource.call(self)
end
|
#forbidden? ⇒ Boolean
61
62
63
64
65
66
67
68
69
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 61
def forbidden?
if application_context.resource_authorizer
!application_context.resource_authorizer.call(self)
elsif PactBroker.configuration.authorize
!PactBroker.configuration.authorize.call(self, {})
else
false
end
end
|
#identifier_from_path ⇒ Object
Also known as:
path_info
Remove the non-path compontents in the path_info (eg. the application context, which is naughtily passed in via the path_info)
72
73
74
75
76
77
78
79
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 72
def identifier_from_path
@identifier_from_path ||= request.path_info.each_with_object({}) do | (key, value), hash|
case value
when String, Symbol, Numeric
hash[key] = value
end
end
end
|
#integration ⇒ Object
Not necessarily an existing integration
232
233
234
235
236
237
238
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 232
def integration
if consumer_specified? && provider_specified?
OpenStruct.new(consumer: consumer, provider: provider)
else
nil
end
end
|
#invalid_json? ⇒ Boolean
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 187
def invalid_json?
begin
char_number, fragment = fragment_before_invalid_utf_8_char(request_body)
if char_number
error_message = message("errors.non_utf_8_char_in_request_body", char_number: char_number, fragment: fragment)
logger.info(error_message)
set_json_error_message(error_message)
true
else
params
false
end
rescue StandardError => e
message = "#{e.cause ? e.cause.class.name : e.class.name} - #{e.message}"
logger.info(message)
set_json_error_message(message)
true
end
end
|
#is_authorized?(authorization_header) ⇒ Boolean
57
58
59
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 57
def is_authorized?()
authenticated?(self, )
end
|
#known_methods ⇒ Object
44
45
46
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 44
def known_methods
super + ["PATCH"]
end
|
48
49
50
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 48
def malformed_request?
content_type_is_json_but_invalid_json_provided?
end
|
270
271
272
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 270
def malformed_request_for_json_with_schema?(schema_to_use = schema, params_to_validate = params)
invalid_json? || validation_errors_for_schema?(schema_to_use, params_to_validate)
end
|
#options ⇒ Object
40
41
42
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 40
def options
{ "Access-Control-Allow-Methods" => allowed_methods.join(", ")}
end
|
#pact ⇒ Object
227
228
229
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 227
def pact
@pact ||= pact_service.find_pact(pact_params)
end
|
#pact_params ⇒ Object
143
144
145
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 143
def pact_params
@pact_params ||= PactBroker::Pacts::PactParams.from_request(request, identifier_from_path)
end
|
#pacticipant ⇒ Object
223
224
225
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 223
def pacticipant
@pacticipant ||= identifier_from_path[:pacticipant_name] && find_pacticipant(identifier_from_path[:pacticipant_name], "pacticipant")
end
|
#pacticipant_name ⇒ Object
179
180
181
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 179
def pacticipant_name
identifier_from_path[:pacticipant_name]
end
|
#pacticipant_specified? ⇒ Boolean
183
184
185
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 183
def pacticipant_specified?
identifier_from_path.key?(:pacticipant_name)
end
|
#pacticipant_version_number ⇒ Object
163
164
165
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 163
def pacticipant_version_number
identifier_from_path[:pacticipant_version_number]
end
|
#params(options = {}) ⇒ Object
rubocop: disable Metrics/CyclomaticComplexity
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 119
def params(options = {})
return options[:default] if options.key?(:default) && request_body.empty?
symbolize_names = !options.key?(:symbolize_names) || options[:symbolize_names]
parsed_params = if symbolize_names
@params_with_symbol_keys ||= JSON.parse(request_body, { symbolize_names: true }.merge(PACT_PARSING_OPTIONS)) else
@params_with_string_keys ||= JSON.parse(request_body, { symbolize_names: false }.merge(PACT_PARSING_OPTIONS)) end
if !parsed_params.is_a?(Hash) && !parsed_params.is_a?(Array)
raise "Expected JSON Object in request body but found #{parsed_params.class.name}"
end
parsed_params
rescue StandardError => e
raise InvalidJsonError.new(e.message)
end
|
#params_with_string_keys ⇒ Object
rubocop: enable Metrics/CyclomaticComplexity
139
140
141
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 139
def params_with_string_keys
params(symbolize_names: false)
end
|
#patch_can_create? ⇒ Boolean
TODO rename to patch_to_create_supported, otherwise it sounds like it’s a policy issue Not a Webmachine method. This is used by security policy code to identify whether a PATCH to a non existing resource can create a new object.
297
298
299
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 297
def patch_can_create?
false
end
|
#provider ⇒ Object
219
220
221
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 219
def provider
@provider ||= identifier_from_path[:provider_name] && find_pacticipant(identifier_from_path[:provider_name], "provider")
end
|
#provider_name ⇒ Object
175
176
177
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 175
def provider_name
identifier_from_path[:provider_name]
end
|
#provider_specified? ⇒ Boolean
171
172
173
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 171
def provider_specified?
identifier_from_path.key?(:provider_name)
end
|
#put_can_create? ⇒ Boolean
TODO rename to put_to_create_supported, otherwise it sounds like it’s a policy issue Not a Webmachine method. This is used by security policy code to identify whether a PUT to a non existing resource can create a new object.
290
291
292
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 290
def put_can_create?
false
end
|
#request_body ⇒ Object
147
148
149
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 147
def request_body
@request_body ||= request.body.to_s
end
|
#request_body_required? ⇒ Boolean
283
284
285
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 283
def request_body_required?
false
end
|
#resource_url ⇒ Object
106
107
108
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 106
def resource_url
request.uri.to_s.gsub(/\?.*/, "").chomp("/")
end
|
#schema ⇒ Object
256
257
258
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 256
def schema
nil
end
|
#ui_base_url ⇒ Object
See comments for base_url in lib/pact_broker/doc/controllers/app.rb
93
94
95
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 93
def ui_base_url
request.env["pactbroker.base_url"] || ""
end
|
#validation_errors_for_schema?(schema_to_use = schema, params_to_validate = params) ⇒ Boolean
260
261
262
263
264
265
266
267
268
|
# File 'lib/pact_broker/api/resources/base_resource.rb', line 260
def validation_errors_for_schema?(schema_to_use = schema, params_to_validate = params)
result = schema_to_use.call(params_to_validate)
if result.errors.any?
set_json_validation_error_messages(result.errors)
true
else
false
end
end
|