Class: CandlepinAPI::Endpoint

Inherits:
Sublime::Hash2Instance show all
Extended by:
Enumerable
Includes:
CandlepinAPI
Defined in:
lib/candlepin-api/base.rb,
lib/candlepin-api/base.rb,
lib/candlepin-api/base.rb,
lib/candlepin-api/base.rb,
lib/candlepin-api/base.rb

Overview

End of class CandlepinAPI::Endpoint

Constant Summary collapse

PathParams =

Array of API-defined keywords for the placeholders in the URI.

[]
PathMap =

Hash mapping values from the URI to keywords. This is needed because the API keywords aren’t completely consistent. The map will resolve various alternatives into the canonical keyword Clonepin uses.

{
}
Verbs =

Hash of HTTP methods mapped to the verb class representing them.

Verb classes self-register here as part of their definitions.

Examples:

Verbs[:GET] => SomeGetAction
{
}
AllowedRoles =

Roles (.e.g, :SUPER_ADMIN) that are permitted to access this verb entry point.

[]
API_Flags =

Restrictions or special qualities of a verb entry point. All default to false; individual class definitions turn appropriate ones on.

{
  :admin_only => false,
  :can_create_owner => false,
  :disallowed => false,
  :internal_only  => false
}
Keys_by_Role =

Different roles can use different keys. The :SUPER_ADMIN role can use ‘em all, but others can’t use values from the URI, for example.

{
}
QueryParams =

See the explanation above about the PathParams and PathMap constants.

[]
QueryMap =
{
}
ReturnType =
{}
HTTPStatusCodes =
[]
VerifiedParams =
[]
TimeLimit =

How long a request is allowed to run without a response.

60

Constants included from CandlepinAPI

Placeholder_RE, VERSION

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from CandlepinAPI

VERSION, basic_auth, basic_auth=, #normalise_rqtype, #regex2printf, server_uri, server_uri=, version

Constructor Details

#initialize(*args) ⇒ Endpoint

Constructor (used only to instantiate for a verb entry point).



920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
# File 'lib/candlepin-api/base.rb', line 920

def initialize(*args)
  #
  # Preset our instance variables.
  #
  @keys   = []
  @pathparams = {}
  @queryparams  = {}
  @role   = nil
  #
  # If we were passed a Rack::Request as the first argument, we're
  # parsing an existing request.  Do it.
  #
  @objtype = :request
  if (args.empty? || args[0].kind_of?(Hash))
    hsh = args[0] || {}
    if (hsh.key?(:header))
      @request_header = hsh[:header]
      hsh = hsh.dup
      hsh.delete(:header)
      args[0] = hsh
    end
  else
    @objtype = :response
    self.request = args.shift
  end
  return super
end

Class Attribute Details

.path_regex_mapObject

Add reader methods that makes sure the instance variables are always hashes.



202
203
204
# File 'lib/candlepin-api/base.rb', line 202

def path_regex_map
  return (@path_regex_map ||= {})
end

.path_string2regexObject

See Also:

  • #path_regex_map


212
213
214
# File 'lib/candlepin-api/base.rb', line 212

def path_string2regex
  return (@path_string2regex ||= {})
end

.path_string_mapObject

See Also:

  • #path_regex_map


207
208
209
# File 'lib/candlepin-api/base.rb', line 207

def path_string_map
  return (@path_string_map ||= {})
end

Instance Attribute Details

#auth_passwordObject

Returns the value of attribute auth_password.



788
789
790
# File 'lib/candlepin-api/base.rb', line 788

def auth_password
  @auth_password
end

#auth_usernameObject

Values of special request header fields.



787
788
789
# File 'lib/candlepin-api/base.rb', line 787

def auth_username
  @auth_username
end

#consumer_uuidObject

Returns the value of attribute consumer_uuid.



791
792
793
# File 'lib/candlepin-api/base.rb', line 791

def consumer_uuid
  @consumer_uuid
end

#entitlement_idObject

Returns the value of attribute entitlement_id.



792
793
794
# File 'lib/candlepin-api/base.rb', line 792

def entitlement_id
  @entitlement_id
end

#keysObject

Shard-determining keys appropriate to the request for which we were instantiated.



836
837
838
# File 'lib/candlepin-api/base.rb', line 836

def keys
  @keys
end

#net_http_requestObject (readonly)

Returns the value of attribute net_http_request.



796
797
798
# File 'lib/candlepin-api/base.rb', line 796

def net_http_request
  @net_http_request
end

#org_idObject

Returns the value of attribute org_id.



790
791
792
# File 'lib/candlepin-api/base.rb', line 790

def org_id
  @org_id
end

#pathparamsObject (readonly)

Instance variables for the values pulled from the URI. We maintain these as an alternate datastore in case there happens to be a named parameter duplicated in both locations. This shouldn’t happen, since pathparam names are represented as symbols and query parameter names as strings.



698
699
700
# File 'lib/candlepin-api/base.rb', line 698

def pathparams
  @pathparams
end

#pool_idObject

Returns the value of attribute pool_id.



793
794
795
# File 'lib/candlepin-api/base.rb', line 793

def pool_id
  @pool_id
end

#queryparamsObject (readonly)

Returns the value of attribute queryparams.



699
700
701
# File 'lib/candlepin-api/base.rb', line 699

def queryparams
  @queryparams
end

#requestObject

Retain the request from which we were built.



841
842
843
# File 'lib/candlepin-api/base.rb', line 841

def request
  @request
end

#request_bodyObject (readonly)

Returns the value of attribute request_body.



843
844
845
# File 'lib/candlepin-api/base.rb', line 843

def request_body
  @request_body
end

#request_headerObject (readonly)

Returns the value of attribute request_header.



842
843
844
# File 'lib/candlepin-api/base.rb', line 842

def request_header
  @request_header
end

#responseObject (readonly)

Returns the value of attribute response.



844
845
846
# File 'lib/candlepin-api/base.rb', line 844

def response
  @response
end

#response_bodyObject (readonly)

Returns the value of attribute response_body.



845
846
847
# File 'lib/candlepin-api/base.rb', line 845

def response_body
  @response_body
end

#response_headerObject (readonly)

Returns the value of attribute response_header.



846
847
848
# File 'lib/candlepin-api/base.rb', line 846

def response_header
  @response_header
end

#usernameObject

Returns the value of attribute username.



794
795
796
# File 'lib/candlepin-api/base.rb', line 794

def username
  @username
end

Class Method Details

.[](key_p) ⇒ Hash

TODO:

Fix bug: The following are coming up empty:

/candlepin//owners/([^/]+)/consumers
/consumers/_%consumer-uuid%/certificates/serials
/owners/([^/]+)/consumers
TODO:

Add [] method to endpoints that looks up verb classes (e.g., ‘endpoint`)

Access the endpoints directly by path. Or by regex. (Complicated, that, since the keys are themselves regexes. Caveat emptor.)

Leading slash problem?

Returns:

  • (Hash)

    Returns a hash for a single match, or an array of ‘{ path-as-regex => hash }` for multiple matches.



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/candlepin-api/base.rb', line 241

def [](key_p)
  #
  # Look for exact matches.
  #
  return result if (result = self.path_regex_map[key_p])
  return result if (result = self.path_string_map[key_p])
  #
  # Try treating the argument as a path and find entries that
  # match it.
  #
  if (key_p.kind_of?(String))
    key = key_p.sub(%r!^.*/candlepin/!, '')
    key.sub!(%r!^/+!, '')
    key.sub!(%r!\?.*!, '')
    result = self.select(:regex) { |pat,klass| key =~ pat }
    unless (result.empty?)
      if (result.size > 1)
        #
        # We have multiple matches.  It's possible that our key
        # has a keyword where some entrypoints expect it but others
        # have a placeholder.  E.g., both of the following will
        # match 'consumers/<consumer-uuid>/certificates/serials',
        # but only the first match is actually correct:
        #
        # ^consumers\/([^\/]+)\/certificates\/serials\/?$
        # ^consumers\/([^\/]+)\/certificates\/([^\/]+)\/?$
        #
        # Cheat by picking the one with the fewest pathparams
        # (and praying).  If more than one have the same value
        # for 'fewest', it's a legitimate duplicate.  That's our
        # assumption and we're sticking to it.
        #
        result.sort! { |a,b|
          aParams = a.values[0].const_get('PathParams')
          bParams = b.values[0].const_get('PathParams')
          aParams.size <=> bParams.size
        }
        minparams = result[0].values[0].const_get('PathParams').size
        result.delete_if { |o| o.values[0].const_get('PathParams').size > minparams }
      end
      result = result.first if (result.size == 1)
      return result
    end
  end
  #
  # Try treating the argument as a regex used to match a path pattern.
  #
  results = self.path_string_map.inject([]) { |memo,tuple|
    (ep, elt) = tuple
    if (ep =~ Regexp.new(key))
      memo << { self.path_string2regex[ep] => elt }
    end
    memo
  }
  return results.empty? ? nil : results
end

.add(klass) ⇒ Object

Add an endpoint class to the map. The endpoint classes invoke this as part of their definitions.



366
367
368
369
370
# File 'lib/candlepin-api/base.rb', line 366

def add(klass)
  self.path_regex_map[klass.path_regex] = klass
  self.path_string_map[klass.path_string] = klass
  self.path_string2regex[klass.path_string] = klass.path_regex
end

.admin_only?Boolean

Helpers for access to the individual flag states.

Returns:

  • (Boolean)


749
750
751
# File 'lib/candlepin-api/base.rb', line 749

def admin_only?
  return const_get('API_Flags')[:admin_only] || false
end

.allowed_rolesObject

Helpers for access to the ‘verb class’ constants.



728
729
730
# File 'lib/candlepin-api/base.rb', line 728

def allowed_roles
  return const_get('AllowedRoles').collect { |k| k.to_sym }
end

.can_create_owner?Boolean

Returns:

  • (Boolean)


752
753
754
# File 'lib/candlepin-api/base.rb', line 752

def can_create_owner?
  return const_get('API_Flags')[:can_create_owner] || false
end

.disallowed?Boolean

Returns:

  • (Boolean)


755
756
757
# File 'lib/candlepin-api/base.rb', line 755

def disallowed?
  return const_get('API_Flags')[:disallowed] || false
end

.each(&block) ⇒ Object

Needed for Enumerable (the registered endpoints are our list).



219
220
221
# File 'lib/candlepin-api/base.rb', line 219

def each(&block)
  return self.path_string_map.each(&block)
end

.endpointObject

Pointer back to the endpoint for this verb.



713
714
715
# File 'lib/candlepin-api/base.rb', line 713

def endpoint
  return self.ancestors.find { |o| o.name =~ %r!(?:^|::)Endpoint_! }
end

.ep2verb(req, &block) ⇒ Object

Turn an entrypoint into an HTTP verb (method)



375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/candlepin-api/base.rb', line 375

def ep2verb(req, &block)
  result = self.select(req, &block)
  #
  # No endpoints matched the URI?  D'oh..
  #
  return nil if (result.empty?)
  #
  # Find the verb class for the endpoint that works for the request.
  #
  result = result.collect { |tuple|
    (regex, endpoint) = tuple
    klass = endpoint.verbs[req.method.to_s.upcase.to_sym]
    klass.new(req) unless (klass.nil?)
  }
  #
  # #collect maintains the array length, so delete the nil elements.
  #
  result.compact!
  #
  # If there's nothing left, we found a matching endpoint, but the
  # HTTP method isn't supported for it.
  #
  if (result.empty?)
    result = nil
  elsif (result.size == 1)
    result = result.first
  end
  #
  # We'll either be returning a scalar or an array, depending on
  # the number of classes that matched the request.  There *should*
  # only be one, but that's for our caller to finesse.
  #
  return result
end

.find(&block) ⇒ Object

def select



320
321
322
323
# File 'lib/candlepin-api/base.rb', line 320

def find(&block)
  result = self.select(&block)
  return result.empty? ? nil : result.first
end

.flagsObject

Return an array of the flags set to ‘true’ for the verb entry point.



742
743
744
# File 'lib/candlepin-api/base.rb', line 742

def flags
  return const_get('API_Flags').collect { |k,v| k.to_sym if (v) }.compact
end

.internal_only?Boolean

Returns:

  • (Boolean)


758
759
760
# File 'lib/candlepin-api/base.rb', line 758

def internal_only?
  return const_get('API_Flags')[:internal_only] || false
end

.key?(key) ⇒ Boolean

def keys

Returns:

  • (Boolean)


341
342
343
# File 'lib/candlepin-api/base.rb', line 341

def key?(key)
  return self.path_regex_map.key?(key) || self.path_string_map.key?(key)
end

.keysObject

def string_keys



337
338
339
# File 'lib/candlepin-api/base.rb', line 337

def keys
  return self.regex_keys
end

.methodObject



737
738
739
# File 'lib/candlepin-api/base.rb', line 737

def verb
  return const_get('Verb').to_sym
end

.path_regexObject

Helper to fetch the URI regular expression for the endpoint. Just to avoid using Foo::URI_Regex constant syntax, which can be a little confusing.



425
426
427
# File 'lib/candlepin-api/base.rb', line 425

def path_regex
  return const_get('URI_Regex')
end

.path_stringObject

As above, except it gets the raw pattern before it’s turned into a regex.



433
434
435
# File 'lib/candlepin-api/base.rb', line 433

def path_string
  return const_get('URI_Regex_String')
end

.pathparamObject

Consult the map to obtain the canonical name for a parameter embedded in the URI. def pparam



418
419
420
421
# File 'lib/candlepin-api/base.rb', line 418

def pparam(name_p)
  name = name_p.to_sym
  return const_get('PathMap')[name].to_sym || name
end

.pparam(name_p) ⇒ Object

Consult the map to obtain the canonical name for a parameter embedded in the URI.



414
415
416
417
# File 'lib/candlepin-api/base.rb', line 414

def pparam(name_p)
  name = name_p.to_sym
  return const_get('PathMap')[name].to_sym || name
end

.qparam(name_p) ⇒ Object

See the explanation above for the pparam class method.



720
721
722
723
# File 'lib/candlepin-api/base.rb', line 720

def qparam(name_p)
  name = name_p.to_s
  return const_get('QueryMap')[name].to_s || name
end

.regex_keysObject

def size



329
330
331
# File 'lib/candlepin-api/base.rb', line 329

def regex_keys
  return self.path_regex_map.keys
end

.select(mode = :regex) ⇒ nil, Array<Hash>

Override the Enumerable method because we don’t fit perfectly.

Parameters:

  • mode (Symbol) (defaults to: :regex)

Returns:

  • (nil, Array<Hash>)


304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/candlepin-api/base.rb', line 304

def select(mode=:regex)
  source = mode.eql?(:regex) ? self.path_regex_map : self.path_string_map
  interim = source.select { |regex,endpoint|
    match = yield(regex, endpoint)
  }
  #
  # We now have an array or arrays.  Yuck.  Turn it back into an
  # array of hashes.
  #
  result = []
  while (tuple = interim.shift)
    result << { tuple[0] => tuple[1] }
  end
  return result
end

.sizeObject

def find



325
326
327
# File 'lib/candlepin-api/base.rb', line 325

def size
  return self.regex_map.size
end

.string_keysObject

def regex_keys



333
334
335
# File 'lib/candlepin-api/base.rb', line 333

def string_keys
  return self.path_string_map.keys
end

.timelimitObject



731
732
733
# File 'lib/candlepin-api/base.rb', line 731

def timelimit
  return const_get('TimeLimit')
end

.valid_response?(rsp) ⇒ Boolean

def valid_responses

Returns:

  • (Boolean)


349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/candlepin-api/base.rb', line 349

def valid_response?(rsp)
  codes = self.const_get('HTTPStatusCodes')
  return false if (codes.empty?)
  if (rsp.kind_of?(Integer))
    code = rsp
  elsif (rsp.kind_of?(String))
    code = rsp.to_i
  elsif (rsp.respond_to?(:code))
    code = rsp.code.to_i
  end
  return codes.include?(code)
end

.valid_responsesObject

def key?



345
346
347
# File 'lib/candlepin-api/base.rb', line 345

def valid_responses
  return self.const_get('HTTPStatusCodes')
end

.verbObject



734
735
736
# File 'lib/candlepin-api/base.rb', line 734

def verb
  return const_get('Verb').to_sym
end

.verbsObject

Another helper to access the map of available verb classes for the endpoint.



441
442
443
# File 'lib/candlepin-api/base.rb', line 441

def verbs
  return const_get('Verbs')
end

Instance Method Details

#admin_only?Boolean

Questions about access to the verb/entrypoint

Returns:

  • (Boolean)


878
879
880
# File 'lib/candlepin-api/base.rb', line 878

def admin_only?
  return self.class.admin_only?
end

#allowed_rolesObject



859
860
861
# File 'lib/candlepin-api/base.rb', line 859

def allowed_roles
  return self.class.allowed_roles
end

#basic_auth(*args_p) ⇒ Object

See Also:

  • CandlepinAPI#basic_auth


461
462
463
464
465
466
467
468
469
470
# File 'lib/candlepin-api/base.rb', line 461

def basic_auth(*args_p)
  unless ([0, 2].include?(args_p.size))
    raise ArgumentError.new('wrong number of arguments ' +
                            "(#{args_p.size} for 0 or 2)")
  end
  if (args_p.size == 2)
    @basic_auth_credentials = args_p.dup
  end
  return @basic_auth_credentials || CandlepinAPI.basic_auth
end

#basic_auth=(username, password) ⇒ Object

See Also:

  • CandlepinAPI#basic_auth=


473
474
475
# File 'lib/candlepin-api/base.rb', line 473

def basic_auth=(username, password)
  return basic_auth(username, password)
end

#basic_auth_fieldObject



910
911
912
913
914
915
# File 'lib/candlepin-api/base.rb', line 910

def basic_auth_field
  return nil unless (self.has_basic_auth?)
  token = AuthHelper_Basic.encode_credentials(@auth_username,
                                              @auth_password)
  return token.chomp
end

#can_create_owner?Boolean

Returns:

  • (Boolean)


881
882
883
# File 'lib/candlepin-api/base.rb', line 881

def can_create_owner?
  return self.class.can_create_owner?
end

#disallowed?Boolean

Returns:

  • (Boolean)


884
885
886
# File 'lib/candlepin-api/base.rb', line 884

def disallowed?
  return self.class.disallowed?
end

#endpointObject



863
864
865
# File 'lib/candlepin-api/base.rb', line 863

def endpoint
  return self.class.endpoint
end

#extract_uri_info(path) ⇒ Object

End of def initialize



948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
# File 'lib/candlepin-api/base.rb', line 948

def extract_uri_info(path)
  uri_parsed = URI.parse(path)
  norm_path = normalise_path(uri_parsed.path)
  #
  # Extract any values embedded in the URI.  These are the
  # 'pathparams', and their names are represented as *symbols* in
  # the various structures.
  #
  unless ((pnames = self.class.const_get('PathParams')).empty?)
    m = norm_path.match(self.class.const_get('URI_Regex'))
    pnames.each_with_index do |pname,poz|
      @pathparams[pname.to_sym] = m.captures[poz]
      self.__send__((pname.to_s + '=').to_sym, m.captures[poz])
    end
  end
  #
  # Repeat for any query-string parameters.
  # Query parameter names are strings, not symbols.
  #
  unless ((pnames = self.class.const_get('QueryParams')).empty?)
    qtuples = uri_parsed.query.split(%r![&;]!)
    qval = qtuples.inject({}) { |memo,tuple|
      (k, v) = tuple.split(%r!=!, 2)
      memo[k] = v
      memo
    }
    pnames.each do |pname|
      @queryparams[pname] = qval[pname]
      self.__send__((pname + '=').to_sym, qval[pname])
    end
  end
end

#flagsObject



867
868
869
# File 'lib/candlepin-api/base.rb', line 867

def flags
  return self.class.flags
end

#has_basic_auth?Boolean

Returns:

  • (Boolean)


906
907
908
# File 'lib/candlepin-api/base.rb', line 906

def has_basic_auth?
  return (! (@auth_username.nil? || @auth_password.nil?))
end

#have_params?Boolean

def missing_params

Returns:

  • (Boolean)


642
643
644
# File 'lib/candlepin-api/base.rb', line 642

def have_params?
  return (self.missing_params.empty?)
end

#internal_only?Boolean

Returns:

  • (Boolean)


887
888
889
# File 'lib/candlepin-api/base.rb', line 887

def internal_only?
  return self.class.internal_only?
end

#is_external?Boolean

Return true if the request header field indicates this request came from Outside.

Returns:

  • (Boolean)


1090
1091
1092
# File 'lib/candlepin-api/base.rb', line 1090

def is_external?
  return (@request.headers['HTTP_CANDLEPIN_CONTEXT'] == 'External')
end

#is_trusted_origin?Boolean

Abstract the check for a trusted IP origin into a do-nothing-else method.

Returns:

  • (Boolean)


1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
# File 'lib/candlepin-api/base.rb', line 1098

def is_trusted_origin?
  #
  # We're paranoid -- there are only a few hosts we intend to trust,
  # and they're all us.  (There remains a danger if the host we're
  # trusting is proxying an external request and didn't sanitise the
  # original request header -- essentially passing us a
  # potentially-spoofed CP-User value.
  #
  trusted_sources = [
                     '127.0.0.1', # IPV4
                     '::1',       # IPV6
                     req['SERVER_ADDR']
                    ]
  return trusted_sources.include?(@request.ip)
end

#is_trusted_request?Boolean

Is this a completely trusted connexion?

Returns:

  • (Boolean)


1077
1078
1079
1080
1081
1082
1083
1084
# File 'lib/candlepin-api/base.rb', line 1077

def is_trusted_request?
  #
  # Shortest path first..  if the client knows the admin credentials,
  # we have to trust it.
  #
  return true if (self.role_is_admin?)
  return false
end

#load_from_nethttp(req) ⇒ Object

End of extract_uri_info



981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
# File 'lib/candlepin-api/base.rb', line 981

def load_from_nethttp(req)
debugger
  #
  # Find any permutation of spelling for the CP-Consumer and CP-User
  # header fields.
  #
  %w( CP-Consumer CP-User ).each do |canon_hfield|
    ivar = '@' + canon_hfield.downcase.gsub(%r!-!, '_')
    pats = []
    pats << canon_hfield.gsub(%r!-!, '_')
    pats << canon_hfield.gsub(%r!_!, '-')
    pats << 'HTTP_' + canon_hfield.gsub(%r!-!, '_')
    pats << 'HTTP_' + canon_hfield.gsub(%r!_!, '-')
    pats.each do |pat|
      if (req.key?(pat))
        instance_variable_set(ivar.to_sym, req[pat])
        break
      end
    end
  end
  #
  # If the entry point has any defined path parameters, suck the
  # values for them into our instance.
  #
  self.extract_uri_info(req.path)
  #
  # Check for auth.
  #
  if (authtoken = req['Authorization'])
    encoded_cred = authtoken.sub(%r!^Basic\s+!i, '')
    if (encoded_cred != authtoken)
      decoded_cred = Base64.decode64(encoded_cred).chomp.strip
      (@auth_username, @auth_password) = decoded_cred.split(%r!:!)
      if (@auth_username.to_s.empty? || @auth_password.to_s.empty?)
        #
        # If either is nil or an empty string, make them both nil.
        # This might break on a blank password, but oh well.
        #
        @auth_username = nil
        @auth_password = nil
      else
        self.check_for_admin
      end
    end
  end
  @body = Proc.new { req.body }
  return req
end

#load_from_rackrequest(req) ⇒ Object

End of def load_from_nethttp



1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
# File 'lib/candlepin-api/base.rb', line 1030

def load_from_rackrequest(req)
  #
  # Find any permutation of spelling for the CP-Consumer and CP-User
  # header fields.  This is a bit complicated because the header
  # fields are kept in a hash and may or may not be case-sensitive.
  #
  %w( CP-Consumer CP-User ).each do |canon_hfield|
    key = re_str = canon_hfield
    ivar = '@' << canon_hfield.gsub(%r!-!, '_').downcase
    pats = []
    pats << %r!^(#{re_str})$!i
    pats << %r!^(#{re_str.gsub(%r!-!, '[-_]')})$!i
    pats << %r!^(HTTP_#{re_str.gsub(%r!-!, '[-_]')})$!i
    pats.each do |re_pat|
      unless ((m = req.env.keys.grep(re_pat)).empty?)
        key = m.first
        instance_variable_set(ivar.to_sym, req.env[key])
        break
      end
    end
  end
  #
  # Use our helper to get fields from the URI.
  #
  self.extract_uri_info(req.path)
  #
  # Any query-string parameters are directly accessible from the
  # request.
  #
  unless ((pnames = self.class.const_get('QueryParams')).empty?)
    pnames.each do |pname|
      @queryparams[pname.to_sym] = req[pname]
      self.__send__((pname.to_s + '=').to_sym, req[pname])
    end
  end
  unless (req.headers['HTTP_AUTHORIZATION'].nil?)
    cred = AuthHelper_Basic.user_name_and_password(req)
    (@auth_username, @auth_password) = cred
    self.check_for_admin
  end
  @body = Proc.new { req.body }
  return req
end

#load_variables_from_trusted_uriObject

We can trust the values in the URI and the query string; use them if we don’t already have better ones.



1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
# File 'lib/candlepin-api/base.rb', line 1118

def load_variables_from_trusted_uri
  #
  # When trusted, the order of preference is most volatile (query-string)
  # to least (URI elements, then header fields).
  #
  @consumer_uuid ||= (@queryparams[:consumer_uuid] \
                      || @pathparams[:consumer_uuid])
  @org_id ||= @queryparams[:org_id] || @pathparams[:org_id]
  @owner_id ||= @queryparams[:owner_id] || @pathparams[:owner_id]
  @entitlement_id ||= (@queryparams[:entitlement_id] \
                       || @pathparams[:entitlement_id])
  @pool_id ||= @queryparams[:pool_id] || @pathparams[:pool_id]
end

#missing_paramsObject

Stuff relating to a specific method/verb applied to the endpoint. These are the bits constituting the ‘verb class’ aspect of this shared class definition.

#missing_params and #have_params? are intended as helpers when building a request.



633
634
635
636
637
638
639
640
# File 'lib/candlepin-api/base.rb', line 633

def missing_params
  pparam_list = self.class.const_get('PathParams')
  return [] if (pparam_list.empty?)
  pparam_list = pparam_list.map { |ppname|
    self.class.const_get('PathMap')[ppname]
  }
  return (pparam_list.select { |s| self.__send__(s.to_sym).nil? })
end

#pparam(name) ⇒ Object Also known as: path_param

Instance methods that simply makes the class methods available at the object level.



608
609
610
# File 'lib/candlepin-api/base.rb', line 608

def pparam(name)
  return self.class.pparam(name)
end

#qparam(name) ⇒ Object

Instance method for the query parameter name canonicalisation. See #pparam above.



772
773
774
# File 'lib/candlepin-api/base.rb', line 772

def qparam(name)
  return self.class.qparam(name)
end

#role_is_admin!Object



898
899
900
901
902
903
904
# File 'lib/candlepin-api/base.rb', line 898

def role_is_admin!
  self.get_admin_credentials
  @auth_username = @admin_username
  @auth_password = @admin_password
  check_for_admin
  return true
end

#role_is_admin?Boolean

Questions about the request this object represents.

Returns:

  • (Boolean)


894
895
896
# File 'lib/candlepin-api/base.rb', line 894

def role_is_admin?
  return @role.eql?(:SUPER_ADMIN)
end

#run_checksObject

End of def load_variables_from_trusted_uri



1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
# File 'lib/candlepin-api/base.rb', line 1132

def run_checks
  #
  # We never, never, *ever* want the SUPER_ADMIN basic-auth credentials
  # to be used from Outside.
  #
  if (self.is_external?)
    #
    # Are the admin credentials being used from Outside?
    #
    if (self.role_is_admin?)
      log_event(:warn,
                'Attempt to use admin credentials via the external context!',
                :run_checks)
      spoor(:event => 'Rejecting external request using SUPER_ADMIN role')
      raise BadCredentialsException.new('Not authorised for this operation')
    end
  end
end

#server_uriObject

See Also:

  • CandlepinAPI#server_uri


483
484
485
486
487
488
489
# File 'lib/candlepin-api/base.rb', line 483

def server_uri
  ancestry = [ self, self.class.ancestors ].flatten
  klass = ancestry.find { |anc|
    anc.respond_to?(:server_uri) && anc.instance_variable_get(:@server_uri)
  }
  return klass.nil? ? nil : klass.instance_variable_get(:@server_uri)
end

#server_uri=(uri) ⇒ Object

See Also:

  • CandlepinAPI#server_uri=


478
479
480
# File 'lib/candlepin-api/base.rb', line 478

def server_uri=(uri)
  @server_uri = uri
end

#submit(options_p = {}) ⇒ Object

def server_uri



491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
# File 'lib/candlepin-api/base.rb', line 491

def submit(options_p={})
  options = options_p.dup
  options.each do |k,val|
    k_sym = k.to_sym
    k_str = k.to_s
    if ((self.class.const_defined?('QueryParams') \
         && self.class.const_get('QueryParams').include?(k_str)) \
        || (self.class.const_defined?('PathParams') \
            && self.class.const_get('PathParams').include?(k_str)))
      self.send((k_str + '=').to_sym, val)
      options.delete(k)
    end
  end
  unless (self.have_params?)
    raise CandlepinAPI::APIError.new('missing required parameters: ' +
                                     self.missing_params.inspect)
  end
  unless (self.server_uri.kind_of?(String))
    raise CandlepinAPI::APIError.new('no server_uri specified ' +
                                     'for request submission')
  end

  uri = URI.parse(self.to_s.split(%r!\s+!)[1])
  rqclass = Net::HTTP.module_eval(self.class.const_get('Verb').to_s.downcase.capitalize)
  rqobj = @net_http_request = rqclass.new(uri.request_uri)
  @request_uri = uri.to_s
  connexion = Net::HTTP.start(uri.host, uri.port)
  #
  # @todo Merge in default options from upstream
  #
  unless (options.key?(:basic_auth) \
          || CandlepinAPI.basic_auth.nil?)
    rqobj.basic_auth(*CandlepinAPI.basic_auth)
  end
  if (@request_header.kind_of?(Hash))
    @request_header.each { |h_k,h_v| rqobj[h_k.to_s] = h_v.to_s }
  end
  options.each do |opname,opval|
    case opname.to_sym
    when :basic_auth
      rqobj.basic_auth(*opval)
    when :headers
      opval.each { |h_k,h_v| rqobj[h_k.to_s] = h_v.to_s }
    when :read_timeout
      connexion.read_timeout = opval
    end
  end
  rqobj['Content-type'] = 'application/json' unless (rqobj['Content-type'])
  @request_body ||= @body
  @raw_response = connexion.request(rqobj, @request_body)
  connexion.finish
  return @raw_response
end

#to_sObject

Our as-a-string rendition is the URI path with all appropriate values filled in. Easily automated; I love that.



549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
# File 'lib/candlepin-api/base.rb', line 549

def to_s
  path = self.class.const_get('URI_Regex_String').sub(%r!^\^!, '/candlepin/')
  path.sub!(%r!/\?\$!, '/')
  path.gsub!(Placeholder_RE, '%s')
  args = self.class.const_get('PathParams').map { |m|
    self.__send__(self.class.const_get('PathMap')[m]) || "{#{m.to_s}}"
  }

  path = path % args
  if (self.server_uri)
    uri = URI.parse(self.server_uri)
    if (uri.path =~ %r!/candlepin$!)
      path.sub!(%r!^/candlepin!, '')
    end
    path.sub!(%r!^/!, '') if (uri.path[-1,1] == '/')
    uri.path << path
    path = uri.to_s
  end
  #
  # The verb-invariant portion is done.  If that's it (i.e., the
  # QueryParams constant isn't defined [as is the case for an endpoint
  # rather than a endpoint+verb], or the list of query-parameter names
  # is empty), we need go no farther.
  #
  if ((! self.class.const_defined?('QueryParams')) \
      || self.class.const_get('QueryParams').empty?)
    return path
  end
  #
  # Load up any query-string arguments into the string.
  #
  qargs = self.class.const_get('QueryParams').map { |k|
    result = nil
    unless ((v = self.__send__(k.to_sym)).nil?)
      result = "#{k.to_s}=#{v}"
    end
    result
  }
  #
  # Any query parameters with no values assigned will be represented
  # in the array by nil, so we can zap 'em out easily.
  #
  qargs.compact!
  #
  # If there really were some values, add them
  #
  unless (qargs.empty?)
    path << '?' << qargs.join('&')
  end
  #
  # Done!  The result is the path plus querystring for the object.
  #
  return path
end

#valid_response?(rsp) ⇒ Boolean

def valid_responses

Returns:

  • (Boolean)


621
622
623
# File 'lib/candlepin-api/base.rb', line 621

def valid_response?(rsp)
  return self.class.valid_response?(rsp)
end

#valid_responsesObject

dev verbs



617
618
619
# File 'lib/candlepin-api/base.rb', line 617

def valid_responses
  return self.class.valid_responses
end

#verbObject



871
872
873
# File 'lib/candlepin-api/base.rb', line 871

def verb
  return self.class.verb
end

#verbsObject



613
614
615
# File 'lib/candlepin-api/base.rb', line 613

def verbs
  return self.class.verbs
end