class ThreeScaleToolbox::OpenAPI::OAS3
OAS3
object
-
OAS3.title
-> string -
OAS3.description
-> string -
OAS3.version
-> string -
OAS3.base_path
-> string -
OAS3.host
-> string -
OAS3.scheme
-> string -
OAS3.operation -> array of operation hash
-
operation hash properties
-
:verb
-
:path
-
:description
-
:operation_id
-
-
-
OAS3.security
-> security hash-
security hash properties
-
:id -> string
-
:type -> string
-
:name -> string
-
:in_f -> string
-
:flow -> symbol (:implicit_flow_enabled, :direct_access_grants_enabled, :service_accounts_enabled, :standard_flow_enabled)
-
:scopes -> array of string
-
-
-
OAS3.service_backend_version
-> string ('1','2','oidc') -
OAS3.set_server_url
-> def(spec, url) -
OAS3.set_oauth2_urls
-> def(spec, scheme_id, authorization_url, token_url)
Constants
- META_SCHEMA_PATH
Attributes
Public Class Methods
# File lib/3scale_toolbox/openapi/oas3.rb, line 37 def self.build(path, raw, validate: true) self.validate(raw) if validate new(path, raw) end
# File lib/3scale_toolbox/openapi/oas3.rb, line 117 def initialize(path, raw) parser = OasParser::Parser.new(path, raw).resolve @definition = OasParser::Definition.new(parser, path) end
# File lib/3scale_toolbox/openapi/oas3.rb, line 32 def self.validate(raw) meta_schema = JSON.parse(File.read(META_SCHEMA_PATH)) JSON::Validator.validate!(meta_schema, raw) end
Public Instance Methods
# File lib/3scale_toolbox/openapi/oas3.rb, line 57 def base_path # If there are many? take first # From https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#openapi-object # If the servers property is not provided, or is an empty array, # the default value would be a Server Object with a url value of / server_objects(&:path).first || '/' end
# File lib/3scale_toolbox/openapi/oas3.rb, line 49 def description definition.info['description'] end
# File lib/3scale_toolbox/openapi/oas3.rb, line 65 def host # If there are many? take first server_objects { |url| "#{url.host}:#{url.port}" }.first end
# File lib/3scale_toolbox/openapi/oas3.rb, line 75 def operations @operations ||= parse_operations end
# File lib/3scale_toolbox/openapi/oas3.rb, line 70 def scheme # If there are many? take first server_objects(&:scheme).first end
# File lib/3scale_toolbox/openapi/oas3.rb, line 79 def security @security ||= parse_security end
# File lib/3scale_toolbox/openapi/oas3.rb, line 83 def service_backend_version # default authentication mode if no security requirement return '1' if security.nil? case security[:type] when 'oauth2' 'oidc' when 'apiKey' '1' else raise ThreeScaleToolbox::Error, "Unexpected security scheme type #{security[:type]}" end end
Update given spec with urls It is expected identified security scheme to be oauth2 type
# File lib/3scale_toolbox/openapi/oas3.rb, line 100 def set_oauth2_urls(spec, sec_scheme_id, authorization_url, token_url) sec_scheme_obj = spec.dig('components', 'securitySchemes', sec_scheme_id) if sec_scheme_obj.nil? || sec_scheme_obj['type'] != 'oauth2' raise ThreeScaleToolbox::Error, "Expected security scheme {#{sec_scheme_id}} not found or not oauth2" end flow_key, flow_obj = sec_scheme_obj['flows'].first flow_obj['authorizationUrl'] = authorization_url if %w[implicit authorizationCode].include?(flow_key) flow_obj['tokenUrl'] = token_url if %w[password clientCredentials authorizationCode].include?(flow_key) end
# File lib/3scale_toolbox/openapi/oas3.rb, line 111 def set_server_url(spec, url) spec['servers'] = [{ 'url' => url }] end
# File lib/3scale_toolbox/openapi/oas3.rb, line 45 def title definition.info['title'] end
# File lib/3scale_toolbox/openapi/oas3.rb, line 53 def version definition.info['version'] end
Private Instance Methods
# File lib/3scale_toolbox/openapi/oas3.rb, line 216 def convert_flow(flow_name) case flow_name when 'implicit' :implicit_flow_enabled when 'password' :direct_access_grants_enabled when 'clientCredentials' :service_accounts_enabled when 'authorizationCode' :standard_flow_enabled else raise ThreeScaleToolbox::Error, "Unexpected security flow field #{flow_name}" end end
# File lib/3scale_toolbox/openapi/oas3.rb, line 142 def erbfying_template(template) # A URL is composed from a limited set of characters belonging to the US-ASCII character set. # These characters include digits (0-9), letters(A-Z, a-z), and a few special characters ("-", ".", "_", "~"). # https://www.urlencoder.io/learn/ tmp = template.gsub '{', '<%=' tmp.gsub '}', '%>' end
# File lib/3scale_toolbox/openapi/oas3.rb, line 194 def fetch_security_scheme(name) security_schemes.fetch(name) do |el| raise ThreeScaleToolbox::Error, "OAS3 parsing error: #{el} not found in security schemes" end end
# File lib/3scale_toolbox/openapi/oas3.rb, line 174 def global_security_requirements @global_security_requirements ||= parse_global_security_reqs end
# File lib/3scale_toolbox/openapi/oas3.rb, line 208 def parse_flows(flows_object) return nil if flows_object.nil? raise ThreeScaleToolbox::Error, 'Invalid OAS: multiple flows' if flows_object.size > 1 convert_flow(flows_object.keys.first) end
# File lib/3scale_toolbox/openapi/oas3.rb, line 178 def parse_global_security_reqs security_requirements.flat_map do |sec_req| sec_req.map do |sec_item_name, sec_item| sec_def = fetch_security_scheme(sec_item_name) { id: sec_item_name, type: sec_def['type'], name: sec_def['name'], in_f: sec_def['in'], flow: parse_flows(sec_def['flows']), scopes: sec_item } end end end
# File lib/3scale_toolbox/openapi/oas3.rb, line 154 def parse_operations definition.paths.flat_map do |path_obj| path_obj.endpoints.flat_map do |endpoint| { verb: endpoint.method, path: endpoint.path.path, description: endpoint.description, operation_id: endpoint.operationId } end end end
# File lib/3scale_toolbox/openapi/oas3.rb, line 167 def parse_security raise ThreeScaleToolbox::Error, 'Invalid OAS: multiple security requirements' \ if global_security_requirements.size > 1 global_security_requirements.first end
OAS3
server object variable substitution
# File lib/3scale_toolbox/openapi/oas3.rb, line 129 def rendered_url(server_object) template = erbfying_template(server_object.fetch('url')) vars = server_object_variables(server_object['variables']) ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding }) end
# File lib/3scale_toolbox/openapi/oas3.rb, line 200 def security_requirements definition.security || [] end
# File lib/3scale_toolbox/openapi/oas3.rb, line 204 def security_schemes (definition.components || {})['securitySchemes'] || {} end
# File lib/3scale_toolbox/openapi/oas3.rb, line 135 def server_object_variables(variables) vars = (variables || {}).each_with_object({}) do |(key, value), a| a[key] = value['default'] end JSON.parse(vars.to_json, symbolize_names: true) end
# File lib/3scale_toolbox/openapi/oas3.rb, line 122 def server_objects servers.map do |s| yield Helper.parse_uri rendered_url(s) end end
# File lib/3scale_toolbox/openapi/oas3.rb, line 150 def servers definition.servers || [] end