oas_parser_reborn 0.25.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 00fed3bd57371f47346c380e218c0907517658ad06e66bc61973d5f4d24c9d14
4
+ data.tar.gz: fb27996947cf7a831de3d319e252b6073b07117d11d49b532586c4e90f88e005
5
+ SHA512:
6
+ metadata.gz: b6c8eb9e53ddef35aa9f1b9156099de649406dacc72a61933344489e244ffa4956c9a5c3042a3ed1d47cbdb20d75bf765d5cedaee2f4b8d6035dd0de2628c180
7
+ data.tar.gz: 4f7ae5c53b96a559a4eee90225d3c7403836a92c3e7793041727e4fc7d857cba317f97cea6ca34949018c3d4dd35d2bfa2b0c580433219d83f461f0466309296
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ ## 0.25.5
2
+
3
+ - Only add token from nested_doc if key exists on nested_doc
4
+
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in oas_parser_reborn.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Adam Butler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,114 @@
1
+
2
+ [![Gem Version](https://badge.fury.io/rb/oas_parser_reborn.svg)](https://rubygems.org/gems/oas_parser_reborn)
3
+ [![Build Status](https://travis-ci.com/MarioRuiz/oas_parser_reborn.svg?branch=master)](https://github.com/MarioRuiz/oas_parser_reborn)
4
+ [![Coverage Status](https://coveralls.io/repos/github/MarioRuiz/oas_parser_reborn/badge.svg?branch=master)](https://coveralls.io/github/MarioRuiz/oas_parser_reborn?branch=master)
5
+ ![Gem](https://img.shields.io/gem/dt/oas_parser_reborn)
6
+ ![GitHub commit activity](https://img.shields.io/github/commit-activity/y/MarioRuiz/oas_parser_reborn)
7
+ ![GitHub last commit](https://img.shields.io/github/last-commit/MarioRuiz/oas_parser_reborn)
8
+ ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/MarioRuiz/oas_parser_reborn)
9
+ This repository is a fork of [nexmo/oas_parser](nexmo/oas_parser) that is no longer maintained. So in case you want to contribute do it here.
10
+
11
+ ---
12
+
13
+ # Open API Definition Parser
14
+
15
+ A Ruby parser for Open API Spec 3.0+ definitions.
16
+
17
+ ### Install
18
+
19
+ Install the gem:
20
+
21
+ ```
22
+ $ gem install oas_parser_reborn
23
+ ```
24
+
25
+ Or add it to your Gemfile:
26
+
27
+ ```ruby
28
+ gem 'oas_parser_reborn'
29
+ ```
30
+
31
+ ### Usage
32
+
33
+ Here is a basic example of how you can traverse through an Open API Spec 3 Definition:
34
+
35
+ ```ruby
36
+ require 'oas_parser_reborn'
37
+
38
+ definition = OasParser::Definition.resolve('petstore.yml')
39
+ # => #<OasParser::Definition>
40
+
41
+ # Get a specific path
42
+ path = definition.path_by_path('/pets')
43
+ # => #<OasParser::Path>
44
+
45
+ # Get all paths.
46
+ definition.paths
47
+ # => [#<OasParser::Path>, ...]
48
+
49
+ # Get a specific endpoint by method
50
+ endpoint = path.endpoint_by_method('get')
51
+ # => #<OasParser::Endpoint>
52
+
53
+ # Get all endpoints
54
+ path.endpoints
55
+ # => [#<OasParser::Endpoint>, ...]
56
+
57
+ # Get endpoint description
58
+ endpoint.description
59
+ # => "Returns all pets from the system that the user has access to"
60
+ ```
61
+
62
+ Checkout the tests and `lib` directory for more classes and methods.
63
+
64
+ ### Development
65
+
66
+ Run tests:
67
+
68
+ ```
69
+ $ rspec
70
+ ```
71
+
72
+ ### Publishing
73
+
74
+ Clone the repo and navigate to its directory:
75
+
76
+ ```
77
+ $ cd oas_parser_reborn
78
+ ```
79
+
80
+ Bump the latest version in `oas_parser_reborn/lib/oas_parser_reborn/version.rb`:
81
+
82
+ ```
83
+ //old
84
+ module OasParser
85
+ VERSION = '1.0.0'.freeze
86
+ end
87
+
88
+ //new
89
+ module OasParser
90
+ VERSION = '1.1.0'.freeze
91
+ end
92
+ ```
93
+
94
+ Build the gem:
95
+
96
+ ```
97
+ $ gem build oas_parser_reborn.gemspec
98
+ ```
99
+
100
+ _This will create a `oas_parser_reborn-1.1.0.gem` file._
101
+
102
+ Push the gem to rubygems.org:
103
+
104
+ ```
105
+ $ gem push oas_parser_reborn-1.1.0.gem
106
+ ```
107
+
108
+ Verify the change was made by checking for the [new version on rubygems.org](https://rubygems.org/gems/oas_parser_reborn)
109
+
110
+
111
+
112
+ ## Contributing
113
+
114
+ Contributions are welcome, please follow [GitHub Flow](https://guides.github.com/introduction/flow/index.html)
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,89 @@
1
+ module OasParser
2
+ class AbstractAttribute
3
+ include OasParser::RawAccessor
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ end
8
+
9
+ def name(format = nil)
10
+ default = @name || raw['name']
11
+ return default unless format
12
+ case format
13
+ when 'text/xml'
14
+ has_xml_name? ? xml_name : default
15
+ else default
16
+ end
17
+ end
18
+
19
+ def enum
20
+ raw['enum'] || (schema ? schema['enum'] : nil)
21
+ end
22
+
23
+ def allOf?
24
+ raw['allOf'] ? true : false
25
+ end
26
+
27
+ def oneOf?
28
+ raw['oneOf'] ? true : false
29
+ end
30
+
31
+ def array?
32
+ type == 'array'
33
+ end
34
+
35
+ def object?
36
+ type == 'object'
37
+ end
38
+
39
+ def collection?
40
+ array? || object?
41
+ end
42
+
43
+ def empty?
44
+ raise 'Called empty? on non collection type' unless collection?
45
+ return true if object? && raw['properties'].blank?
46
+ return true if array? && items.blank?
47
+ false
48
+ end
49
+
50
+ def properties
51
+ return convert_property_schema_to_properties(raw) if (oneOf? || allOf?)
52
+ return nil unless collection?
53
+ return [] if empty?
54
+ return convert_property_schema_to_properties(raw['properties']) if object?
55
+ return convert_property_schema_to_properties(items) if array?
56
+ nil
57
+ end
58
+
59
+ def has_xml_options?
60
+ raw['xml'].present?
61
+ end
62
+
63
+ def is_xml_attribute?
64
+ return false unless has_xml_options?
65
+ raw['xml']['attribute'] || false
66
+ end
67
+
68
+ def is_xml_text?
69
+ # See: https://github.com/OAI/OpenAPI-Specification/issues/630#issuecomment-350680346
70
+ return false unless has_xml_options?
71
+ return true if raw['xml']['text'] || false
72
+ raw['xml']['x-text'] || false
73
+ end
74
+
75
+ def has_xml_name?
76
+ return false unless has_xml_options?
77
+ xml_name || false
78
+ end
79
+
80
+ def xml_name
81
+ raw['xml']['name']
82
+ end
83
+
84
+ def subproperties_are_one_of_many?
85
+ return false unless array?
86
+ items['oneOf'].present?
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,20 @@
1
+ module OasParser
2
+ class Callback < Payload
3
+ include OasParser::RawAccessor
4
+ raw_keys :description, :content
5
+
6
+ attr_accessor :endpoint, :name, :raw
7
+
8
+ def initialize(endpoint, name, raw)
9
+ @endpoint = endpoint
10
+ @name = name
11
+ @raw = raw
12
+ end
13
+
14
+ def paths
15
+ raw.map do |path, definition|
16
+ OasParser::Path.new(self, path, definition)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,61 @@
1
+ require 'mustermann/template'
2
+
3
+ module OasParser
4
+ class Definition
5
+ include OasParser::RawAccessor
6
+ raw_keys :info, :servers, :components, :openapi
7
+ attr_reader :path
8
+
9
+ attr_accessor :raw
10
+
11
+ def self.resolve(path)
12
+ raw = Parser.resolve(path)
13
+ Definition.new(raw, path)
14
+ end
15
+
16
+ def initialize(raw, path)
17
+ @raw = raw
18
+ @path = path
19
+ end
20
+
21
+ def format
22
+ File.extname(@path).sub('.', '')
23
+ end
24
+
25
+ def paths
26
+ raw['paths'].map do |path, definition|
27
+ OasParser::Path.new(self, path, definition)
28
+ end
29
+ end
30
+
31
+ def path_by_path(path)
32
+ definition = raw['paths'][path]
33
+ return OasParser::Path.new(self, path, definition) if definition
34
+ key = raw['paths'].keys.detect do |path_entry|
35
+ Mustermann::Template.new(path_entry).match(path)
36
+ end
37
+ definition = raw['paths'][key]
38
+ raise OasParser::PathNotFound.new("Path not found: '#{path}'") unless definition
39
+ OasParser::Path.new(self, key, definition)
40
+ end
41
+
42
+ def security
43
+ raw['security'] || []
44
+ end
45
+
46
+ def tags
47
+ raw['tags'] || []
48
+ end
49
+
50
+ def endpoints
51
+ paths.flat_map(&:endpoints)
52
+ end
53
+
54
+ def webhooks
55
+ return [] unless raw['webhooks']
56
+ raw['webhooks'].map do |name, definition|
57
+ OasParser::Webhook.new(self, name, definition)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,137 @@
1
+ module OasParser
2
+ class Endpoint
3
+ include OasParser::RawAccessor
4
+ raw_keys :summary, :description, :operationId, :tags, :required
5
+
6
+ attr_accessor :path, :method, :raw
7
+
8
+ def initialize(path, method, raw)
9
+ @path = path
10
+ @method = method
11
+ @raw = raw
12
+ end
13
+
14
+ def definition
15
+ path.definition
16
+ end
17
+
18
+ def operation_id
19
+ operationId
20
+ end
21
+
22
+ def parameters
23
+ security_schema_parameters + local_parameters + path.parameters
24
+ end
25
+
26
+ def path_parameters
27
+ parameters.select { |parameter| parameter.in == 'path' }
28
+ end
29
+
30
+ def query_parameters
31
+ parameters.select { |parameter| parameter.in == 'query' }
32
+ end
33
+
34
+ def security_schema_parameters
35
+ raw_security_schema_parameters = security_schemes.select do |security_schema|
36
+ security_schema['in'].present? && security_schema['in'].present?
37
+ end
38
+
39
+ security_schema_parameter_defaults = {
40
+ 'type' => 'string',
41
+ 'example' => 'abc123',
42
+ 'default' => false,
43
+ }
44
+
45
+ raw_security_schema_parameters.map do |definition|
46
+ definition = security_schema_parameter_defaults.merge(definition)
47
+ OasParser::Parameter.new(self, definition)
48
+ end
49
+ end
50
+
51
+ def parameter_by_name(name)
52
+ parameters.each do |parameter|
53
+ return parameter if parameter.name == name
54
+ end
55
+
56
+ raise OasParser::ParameterNotFound.new("Parameter not found: '#{name}'")
57
+ end
58
+
59
+ def request_body
60
+ return false unless raw['requestBody']
61
+ OasParser::RequestBody.new(self, raw['requestBody'])
62
+ end
63
+
64
+ def responses
65
+ raw['responses'].map do |code, definition|
66
+ OasParser::Response.new(self, code, definition)
67
+ end
68
+ end
69
+
70
+ def response_by_code(code, use_default: false)
71
+ definition = raw['responses'][code]
72
+ definition ||= raw['responses']['default'] if use_default
73
+ raise OasParser::ResponseCodeNotFound.new("Response code not found: '#{code}'") unless definition
74
+ OasParser::Response.new(self, code, definition)
75
+ end
76
+
77
+ def security
78
+ raw['security'] || []
79
+ end
80
+
81
+ def callbacks
82
+ return [] unless raw['callbacks']
83
+ raw['callbacks'].map do |name, definition|
84
+ OasParser::Callback.new(self, name, definition)
85
+ end
86
+ end
87
+
88
+ def callback_by_name(name)
89
+ definition = raw['callbacks'][name]
90
+ raise OasParser::CallbackNotFound.new("Callback not found: '#{name}'") unless definition
91
+ OasParser::Callback.new(self, name, definition)
92
+ end
93
+
94
+ def jwt?
95
+ return false unless security
96
+
97
+ security_schemes.each do |security_schema|
98
+ return true if security_schema['bearerFormat'] == 'JWT'
99
+ end
100
+
101
+ false
102
+ end
103
+
104
+ def basic_auth?
105
+ return false unless security
106
+
107
+ security_schemes.each do |security_schema|
108
+ return true if security_schema['type'] == 'http' && security_schema['scheme'] == 'basic'
109
+ end
110
+
111
+ false
112
+ end
113
+
114
+ def security_schemes
115
+ security_schemes = security.flat_map(&:keys)
116
+
117
+ if definition
118
+ security_schemes = security_schemes + definition.security.flat_map(&:keys)
119
+ end
120
+
121
+ security_schemes = security_schemes.uniq
122
+
123
+ security_schemes.map do |security_scheme_name|
124
+ definition.components['securitySchemes'][security_scheme_name]
125
+ end
126
+ end
127
+
128
+ private
129
+
130
+ def local_parameters
131
+ return [] unless raw['parameters']
132
+ raw['parameters'].map do |definition|
133
+ OasParser::Parameter.new(self, definition)
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,8 @@
1
+ module OasParser
2
+ class Error < StandardError; end
3
+ class CallbackNotFound < Error; end
4
+ class MethodNotFound < Error; end
5
+ class ParameterNotFound < Error; end
6
+ class PathNotFound < Error; end
7
+ class ResponseCodeNotFound < Error; end
8
+ end
@@ -0,0 +1,44 @@
1
+ module OasParser
2
+ class Parameter < AbstractAttribute
3
+ raw_keys :in, :description, :style, :schema,
4
+ :minimum, :maximum, :required, :nullable
5
+
6
+ attr_accessor :owner, :raw
7
+
8
+ def initialize(owner, raw)
9
+ super(raw['name'])
10
+ @owner = owner
11
+ @raw = raw
12
+ end
13
+
14
+ def type
15
+ raw['type'] || (schema ? schema['type'] : nil)
16
+ end
17
+
18
+ def format
19
+ raw['format'] || (schema ? schema['format'] : nil)
20
+ end
21
+
22
+ def items
23
+ schema['items']
24
+ end
25
+
26
+ def example
27
+ raw['example'] || (schema ? schema['example'] : nil)
28
+ end
29
+
30
+ def default
31
+ raw['default'] || (schema ? schema['default'] : nil)
32
+ end
33
+
34
+ def nullable?
35
+ raw['nullable'] || (schema ? schema['nullable'] : nil )
36
+ end
37
+
38
+ def convert_property_schema_to_properties(schema)
39
+ schema.map do |name, definition|
40
+ OasParser::Property.new(self, raw, name, definition)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,77 @@
1
+ module OasParser
2
+ class Parser
3
+ def self.resolve(path)
4
+ content = YAML.load_file(path)
5
+ Parser.new(path, content).resolve
6
+ end
7
+
8
+ def initialize(path, content)
9
+ @path = path
10
+ @content = content
11
+ end
12
+
13
+ def resolve
14
+ deeply_expand_refs(@content, nil)
15
+ end
16
+
17
+ private
18
+
19
+ def deeply_expand_refs(fragment, path)
20
+ fragment, current_path = expand_refs(fragment, path)
21
+
22
+ if fragment.is_a?(Hash)
23
+ fragment.reduce({}) do |hash, (k, v)|
24
+ hash.merge(k => deeply_expand_refs(v, "#{current_path}/#{k}"))
25
+ end
26
+ elsif fragment.is_a?(Array)
27
+ fragment.map { |e| deeply_expand_refs(e, current_path) }
28
+ else
29
+ fragment
30
+ end
31
+ end
32
+
33
+ def expand_refs(fragment, current_path)
34
+ unless fragment.is_a?(Hash) && fragment.key?("$ref")
35
+ return [fragment, current_path]
36
+ end
37
+
38
+ ref = fragment["$ref"]
39
+
40
+ if ref =~ /^#/
41
+ expand_pointer(ref, current_path)
42
+ elsif ref =~ /^(http(s)?|\/\/)/
43
+ expand_url(ref)
44
+ else
45
+ expand_file(ref)
46
+ end
47
+ end
48
+
49
+ def expand_file(ref)
50
+ absolute_path = File.expand_path(File.join("..", ref), @path)
51
+ absolute_path, local_reference = absolute_path.split('#')
52
+ resolved_remote_reference = Parser.resolve(absolute_path)
53
+
54
+ if local_reference
55
+ pointer = OasParser::Pointer.new(local_reference)
56
+ return pointer.resolve(resolved_remote_reference)
57
+ end
58
+
59
+ resolved_remote_reference
60
+ end
61
+
62
+ def expand_pointer(ref, current_path)
63
+ pointer = OasParser::Pointer.new(ref)
64
+
65
+ if pointer.circular_reference?(current_path)
66
+ { "$ref" => ref }
67
+ else
68
+ fragment = pointer.resolve(@content)
69
+ expand_refs(fragment, current_path + pointer.escaped_pointer)
70
+ end
71
+ end
72
+
73
+ def expand_url(ref)
74
+ raise 'Expanding URL References is not supported'
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,45 @@
1
+ module OasParser
2
+ class Path
3
+ attr_accessor :owner, :path, :raw
4
+
5
+ def initialize(owner, path, raw)
6
+ @owner = owner
7
+ @path = path
8
+ @raw = raw
9
+ end
10
+
11
+ def endpoints
12
+ a = raw.map do |method, definition|
13
+ next unless %w[get head post put patch delete trace options].include? method
14
+ OasParser::Endpoint.new(self, method, definition)
15
+ end
16
+
17
+ a.compact
18
+ end
19
+
20
+ def endpoint_by_method(method)
21
+ definition = raw[method]
22
+ raise OasParser::MethodNotFound.new("HTTP method not found: '#{method}'") unless definition
23
+ OasParser::Endpoint.new(self, method, definition)
24
+ end
25
+
26
+ def parameter_keys
27
+ path.scan(/{(.+?)}/).flatten
28
+ end
29
+
30
+ def parameters
31
+ return [] unless raw['parameters']
32
+ raw['parameters'].map do |definition|
33
+ OasParser::Parameter.new(self, definition)
34
+ end
35
+ end
36
+
37
+ def definition
38
+ owner if owner.class == OasParser::Definition
39
+ end
40
+
41
+ def callback
42
+ owner if owner.class == OasParser::Callback
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ module OasParser
2
+ class Payload
3
+ def formats
4
+ return [] unless content
5
+ content.keys
6
+ end
7
+
8
+ def schema(format)
9
+ content[format]['schema']
10
+ end
11
+
12
+ def split_schemas(format)
13
+ content[format]['schema']['oneOf']
14
+ end
15
+
16
+ def exhibits_one_of_multiple_schemas?(format)
17
+ return false unless content
18
+ schema(format).keys.include?('oneOf')
19
+ end
20
+ end
21
+ end