class PactBroker::Api::Resources::BaseResource

Attributes

user[RW]

Public Class Methods

new() click to toggle source
# 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

Public Instance Methods

any_request_body?() click to toggle source
# 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) click to toggle source
# 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() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 244
def application_context
  request.path_info[:application_context]
end
base_url() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 83
def base_url
  # Have to use something for the base URL here - we can't use an empty string as we can in the UI.
  # Can't work out if cache poisoning is a vulnerability for APIs or not.
  # Using the request base URI as a fallback if the base_url is not configured may be a vulnerability,
  # but the documentation recommends that the
  # base_url should be set in the configuration to mitigate this.
  request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp("/")
end
charsets_provided() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 97
def charsets_provided
  [["utf-8", :encode]]
end
consumer() click to toggle source
# 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() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 155
def consumer_name
  identifier_from_path[:consumer_name]
end
consumer_specified?() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 167
def consumer_specified?
  identifier_from_path.key?(:consumer_name)
end
consumer_version_number() click to toggle source
# 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?() click to toggle source

Ensure we have valid JSON if a JSON body is required OR if a body has been provided

# 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?() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 279
def content_type_json?
  request.content_type&.include?("json")
end
database_connector() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 240
def database_connector
  request.env["pactbroker.database_connector"]
end
decorator_class(name) click to toggle source
# 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 = {}) click to toggle source
# 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 = {}) click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 114
def decorator_options options = {}
  { user_options: decorator_context(options) }
end
encode(body) click to toggle source

We only use utf-8 so leave encoding as it is

# File lib/pact_broker/api/resources/base_resource.rb, line 102
def encode(body)
  body
end
find_pacticipant(name, role) click to toggle source
# 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() click to toggle source
# 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?() click to toggle source
# 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() click to toggle source

Remove the non-path compontents in the path_info (eg. the application context, which is naughtily passed in via the path_info)

# 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
Also aliased as: path_info
integration() click to toggle source

Not necessarily an existing integration

# 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?() click to toggle source
# 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) click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 57
def is_authorized?(authorization_header)
  authenticated?(self, authorization_header)
end
known_methods() click to toggle source
Calls superclass method
# File lib/pact_broker/api/resources/base_resource.rb, line 44
def known_methods
  super + ["PATCH"]
end
malformed_request?() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 48
def malformed_request?
  content_type_is_json_but_invalid_json_provided?
end
malformed_request_for_json_with_schema?(schema_to_use = schema, params_to_validate = params) click to toggle source
# 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() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 40
def options
  { "Access-Control-Allow-Methods" => allowed_methods.join(", ")}
end
pact() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 227
def pact
  @pact ||= pact_service.find_pact(pact_params)
end
pact_params() click to toggle source
# 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() click to toggle source
# 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() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 179
def pacticipant_name
  identifier_from_path[:pacticipant_name]
end
pacticipant_specified?() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 183
def pacticipant_specified?
  identifier_from_path.key?(:pacticipant_name)
end
pacticipant_version_number() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 163
def pacticipant_version_number
  identifier_from_path[:pacticipant_version_number]
end
params(options = {}) click to toggle source

rubocop: disable Metrics/CyclomaticComplexity

# 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)) #Not load! Otherwise it will try to load Ruby classes.
                  else
                    @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.
                  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() click to toggle source

rubocop: enable Metrics/CyclomaticComplexity

# File lib/pact_broker/api/resources/base_resource.rb, line 139
def params_with_string_keys
  params(symbolize_names: false)
end
patch_can_create?() click to toggle source

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.

# File lib/pact_broker/api/resources/base_resource.rb, line 297
def patch_can_create?
  false
end
path_info()
provider() click to toggle source
# 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() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 175
def provider_name
  identifier_from_path[:provider_name]
end
provider_specified?() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 171
def provider_specified?
  identifier_from_path.key?(:provider_name)
end
put_can_create?() click to toggle source

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.

# File lib/pact_broker/api/resources/base_resource.rb, line 290
def put_can_create?
  false
end
request_body() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 147
def request_body
  @request_body ||= request.body.to_s
end
request_body_required?() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 283
def request_body_required?
  false
end
resource_url() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 106
def resource_url
  request.uri.to_s.gsub(/\?.*/, "").chomp("/")
end
schema() click to toggle source
# File lib/pact_broker/api/resources/base_resource.rb, line 256
def schema
  nil
end
ui_base_url() click to toggle source

See comments for base_url in lib/pact_broker/doc/controllers/app.rb

# 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) click to toggle source
# 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