grape-swagger 2.1.2 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +111 -107
- data/README.md +150 -29
- data/RELEASING.md +8 -8
- data/grape-swagger.gemspec +1 -2
- data/lib/grape-swagger/doc_methods/build_model_definition.rb +1 -1
- data/lib/grape-swagger/doc_methods/format_data.rb +1 -1
- data/lib/grape-swagger/doc_methods/move_params.rb +1 -1
- data/lib/grape-swagger/doc_methods/parse_params.rb +4 -2
- data/lib/grape-swagger/doc_methods.rb +0 -1
- data/lib/grape-swagger/endpoint.rb +17 -43
- data/lib/grape-swagger/errors.rb +2 -0
- data/lib/grape-swagger/request_param_parser_registry.rb +48 -0
- data/lib/grape-swagger/{endpoint/params_parser.rb → request_param_parsers/body.rb} +21 -22
- data/lib/grape-swagger/request_param_parsers/headers.rb +33 -0
- data/lib/grape-swagger/request_param_parsers/route.rb +66 -0
- data/lib/grape-swagger/token_owner_resolver.rb +101 -0
- data/lib/grape-swagger/version.rb +1 -1
- data/lib/grape-swagger.rb +12 -5
- metadata +10 -21
- data/lib/grape-swagger/doc_methods/headers.rb +0 -20
data/README.md
CHANGED
|
@@ -3,22 +3,92 @@
|
|
|
3
3
|
[](https://coveralls.io/github/ruby-grape/grape-swagger?branch=master)
|
|
4
4
|
[](https://codeclimate.com/github/ruby-grape/grape-swagger)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
# Table of Contents
|
|
7
|
+
|
|
8
|
+
- [What is grape-swagger? ](#what-is-grape-swagger-)
|
|
9
|
+
- [Related Projects ](#related-projects-)
|
|
10
|
+
- [Compatibility ](#compatibility-)
|
|
11
|
+
- [Swagger-Spec ](#swagger-spec-)
|
|
12
|
+
- [Installation ](#installation-)
|
|
13
|
+
- [Upgrade](#upgrade)
|
|
14
|
+
- [Usage ](#usage-)
|
|
15
|
+
- [Model Parsers ](#model-parsers-)
|
|
16
|
+
- [Custom Model Parsers](#custom-model-parsers)
|
|
17
|
+
- [insert_before](#insert_before)
|
|
18
|
+
- [insert_after](#insert_after)
|
|
19
|
+
- [CORS](#cors)
|
|
20
|
+
- [Configure ](#configure-)
|
|
21
|
+
- [host: ](#host-)
|
|
22
|
+
- [base_path: ](#base_path-)
|
|
23
|
+
- [mount_path: ](#mount_path-)
|
|
24
|
+
- [add_base_path: ](#add_base_path-)
|
|
25
|
+
- [add_root: ](#add_root-)
|
|
26
|
+
- [add_version: ](#add_version-)
|
|
27
|
+
- [doc_version: ](#doc_version-)
|
|
28
|
+
- [endpoint_auth_wrapper: ](#endpoint_auth_wrapper-)
|
|
29
|
+
- [swagger_endpoint_guard: ](#swagger_endpoint_guard-)
|
|
30
|
+
- [token_owner: ](#token_owner-)
|
|
31
|
+
- [security_definitions: ](#security_definitions-)
|
|
32
|
+
- [security: ](#security-)
|
|
33
|
+
- [models: ](#models-)
|
|
34
|
+
- [tags: ](#tags-)
|
|
35
|
+
- [hide_documentation_path: (default: true) ](#hide_documentation_path-default-true-)
|
|
36
|
+
- [info: ](#info-)
|
|
37
|
+
- [array_use_braces: ](#array_use_braces-)
|
|
38
|
+
- [api_documentation](#api_documentation)
|
|
39
|
+
- [specific_api_documentation](#specific_api_documentation)
|
|
40
|
+
- [consumes](#consumes)
|
|
41
|
+
- [produces](#produces)
|
|
42
|
+
- [Routes Configuration ](#routes-configuration-)
|
|
43
|
+
- [Swagger Header Parameters ](#swagger-header-parameters--)
|
|
44
|
+
- [Hiding an Endpoint ](#hiding-an-endpoint-)
|
|
45
|
+
- [Overriding Auto-Generated Nicknames ](#overriding-auto-generated-nicknames-)
|
|
46
|
+
- [Specify endpoint details ](#specify-endpoint-details-)
|
|
47
|
+
- [Overriding the route summary ](#overriding-the-route-summary-)
|
|
48
|
+
- [Overriding the tags ](#overriding-the-tags-)
|
|
49
|
+
- [Deprecating routes ](#deprecating-routes-)
|
|
50
|
+
- [Overriding the name of the body parameter ](#overriding-the-name-of-the-body-parameter-)
|
|
51
|
+
- [Defining an endpoint as an array ](#defining-an-endpoint-as-an-array-)
|
|
52
|
+
- [Using an options hash ](#using-an-options-hash-)
|
|
53
|
+
- [Overriding parameter type ](#overriding-parameter-type-)
|
|
54
|
+
- [Overriding data type of the parameter ](#overriding-data-type-of-the-parameter-)
|
|
55
|
+
- [Multiple types ](#multiple-types-)
|
|
56
|
+
- [Array of data type ](#array-of-data-type-)
|
|
57
|
+
- [Collection format of arrays ](#collection-format-of-arrays-)
|
|
58
|
+
- [Hiding parameters ](#hiding-parameters-)
|
|
59
|
+
- [Setting a Swagger default value ](#setting-a-swagger-default-value-)
|
|
60
|
+
- [Setting additionalProperties for object-type parameters ](#setting-additionalproperties-for-object-type-parameters-)
|
|
61
|
+
- [Allow any additional properties](#allow-any-additional-properties)
|
|
62
|
+
- [Allow any additional properties of a particular type](#allow-any-additional-properties-of-a-particular-type)
|
|
63
|
+
- [Allow any additional properties matching a defined schema](#allow-any-additional-properties-matching-a-defined-schema)
|
|
64
|
+
- [Example parameter value ](#example-parameter-value-)
|
|
65
|
+
- [Expose nested namespace as standalone route](#expose-nested-namespace-as-standalone-route)
|
|
66
|
+
- [With a custom name](#with-a-custom-name)
|
|
67
|
+
- [Response documentation ](#response-documentation-)
|
|
68
|
+
- [Changing default status codes ](#changing-default-status-codes-)
|
|
69
|
+
- [Multiple status codes for response ](#multiple-status-codes-for-response-)
|
|
70
|
+
- [File response ](#file-response-)
|
|
71
|
+
- [Default response ](#default-response-)
|
|
72
|
+
- [Extensions ](#extensions-)
|
|
73
|
+
- [Response examples documentation ](#response-examples-documentation-)
|
|
74
|
+
- [Response headers documentation ](#response-headers-documentation-)
|
|
75
|
+
- [Adding root element to responses ](#adding-root-element-to-responses-)
|
|
76
|
+
- [Multiple present Response ](#multiple-present-response-)
|
|
77
|
+
- [Using Grape Entities ](#using-grape-entities-)
|
|
78
|
+
- [Documented class/definition](#documented-classdefinition)
|
|
79
|
+
- [Relationships](#relationships)
|
|
80
|
+
- [1xN](#1xn)
|
|
81
|
+
- [1x1](#1x1)
|
|
82
|
+
- [Inheritance with allOf and discriminator](#inheritance-with-allof-and-discriminator)
|
|
83
|
+
- [Securing the Swagger UI ](#securing-the-swagger-ui-)
|
|
84
|
+
- [Example ](#example-)
|
|
85
|
+
- [Grouping the API list using Namespace](#grouping-the-api-list-using-namespace)
|
|
86
|
+
- [Example Code](#example-code)
|
|
87
|
+
- [Rake Tasks ](#rake-tasks-)
|
|
88
|
+
- [OpenApi/Swagger Documentation](#openapiswagger-documentation)
|
|
89
|
+
- [OpenApi/Swagger Validation](#openapiswagger-validation)
|
|
90
|
+
- [Contributing to grape-swagger](#contributing-to-grape-swagger)
|
|
91
|
+
- [Copyright and License](#copyright-and-license)
|
|
22
92
|
|
|
23
93
|
## What is grape-swagger? <a name="what"></a>
|
|
24
94
|
|
|
@@ -43,18 +113,19 @@ This screenshot is based on the [Hussars](https://github.com/LeFnord/hussars) sa
|
|
|
43
113
|
|
|
44
114
|
The following versions of grape, grape-entity and grape-swagger can currently be used together.
|
|
45
115
|
|
|
46
|
-
| grape-swagger
|
|
47
|
-
|
|
|
48
|
-
| 0.10.5
|
|
49
|
-
| 0.11.0
|
|
50
|
-
| 0.25.2
|
|
51
|
-
| 0.26.0
|
|
52
|
-
| 0.27.0
|
|
53
|
-
| 0.32.0
|
|
54
|
-
| 0.34.0
|
|
55
|
-
| >= 1.0.0
|
|
56
|
-
| >= 2.0.0
|
|
57
|
-
| >= 2.0.0 ...
|
|
116
|
+
| grape-swagger | swagger spec | grape | grape-entity | representable |
|
|
117
|
+
| --------------------- | ------------ | ----------------------- | ------------ | ------------- |
|
|
118
|
+
| 0.10.5 | 1.2 | >= 0.10.0 ... <= 0.14.0 | < 0.5.0 | n/a |
|
|
119
|
+
| 0.11.0 | 1.2 | >= 0.16.2 | < 0.5.0 | n/a |
|
|
120
|
+
| 0.25.2 | 2.0 | >= 0.14.0 ... <= 0.18.0 | <= 0.6.0 | >= 2.4.1 |
|
|
121
|
+
| 0.26.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | <= 0.6.1 | >= 2.4.1 |
|
|
122
|
+
| 0.27.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | >= 0.5.0 | >= 2.4.1 |
|
|
123
|
+
| 0.32.0 | 2.0 | >= 0.16.2 | >= 0.5.0 | >= 2.4.1 |
|
|
124
|
+
| 0.34.0 | 2.0 | >= 0.16.2 ... < 1.3.0 | >= 0.5.0 | >= 2.4.1 |
|
|
125
|
+
| >= 1.0.0 | 2.0 | >= 1.3.0 | >= 0.5.0 | >= 2.4.1 |
|
|
126
|
+
| >= 2.0.0 | 2.0 | >= 1.7.0 | >= 0.5.0 | >= 2.4.1 |
|
|
127
|
+
| >= 2.0.0 ... <= 2.1.2 | 2.0 | >= 1.8.0 ... < 2.3.0 | >= 0.5.0 | >= 2.4.1 |
|
|
128
|
+
| > 2.1.2 | 2.0 | >= 1.8.0 ... < 4.0 | >= 0.5.0 | >= 2.4.1 |
|
|
58
129
|
|
|
59
130
|
|
|
60
131
|
## Swagger-Spec <a name="swagger-spec"></a>
|
|
@@ -1446,7 +1517,6 @@ The result will look like following:
|
|
|
1446
1517
|
Add the [grape-entity](https://github.com/ruby-grape/grape-entity) and [grape-swagger-entity](https://github.com/ruby-grape/grape-swagger-entity) gem to your Gemfile.
|
|
1447
1518
|
|
|
1448
1519
|
The following example exposes statuses. And exposes statuses documentation adding :type, :desc and :required.
|
|
1449
|
-
The documented class/definition name could be set via `#entity_name`.
|
|
1450
1520
|
|
|
1451
1521
|
```ruby
|
|
1452
1522
|
module API
|
|
@@ -1489,6 +1559,57 @@ module API
|
|
|
1489
1559
|
end
|
|
1490
1560
|
```
|
|
1491
1561
|
|
|
1562
|
+
### Documented class/definition
|
|
1563
|
+
|
|
1564
|
+
You can set the name of the Entity when being documented via `#entity_name`:
|
|
1565
|
+
|
|
1566
|
+
```ruby
|
|
1567
|
+
module API
|
|
1568
|
+
module Entities
|
|
1569
|
+
class Status < Grape::Entity
|
|
1570
|
+
expose :text, documentation: { type: 'string', desc: 'Status update text.', required: true }
|
|
1571
|
+
end
|
|
1572
|
+
|
|
1573
|
+
class Link < Grape::Entity
|
|
1574
|
+
expose :href, documentation: { type: 'url' }
|
|
1575
|
+
|
|
1576
|
+
def self.entity_name
|
|
1577
|
+
'LinkedStatus'
|
|
1578
|
+
end
|
|
1579
|
+
|
|
1580
|
+
end
|
|
1581
|
+
end
|
|
1582
|
+
end
|
|
1583
|
+
```
|
|
1584
|
+
Should generate the following definitions in your swagger json:
|
|
1585
|
+
|
|
1586
|
+
```json
|
|
1587
|
+
{
|
|
1588
|
+
"definitions": {
|
|
1589
|
+
"API_Entities_Status": {
|
|
1590
|
+
"type": "object",
|
|
1591
|
+
"properties": {
|
|
1592
|
+
"text": {
|
|
1593
|
+
"type": "string",
|
|
1594
|
+
"description": "Status update text.",
|
|
1595
|
+
},
|
|
1596
|
+
},
|
|
1597
|
+
"required": [
|
|
1598
|
+
"text",
|
|
1599
|
+
],
|
|
1600
|
+
"description": "API_Entities_Pet model"
|
|
1601
|
+
},
|
|
1602
|
+
"LinkedStatus": {
|
|
1603
|
+
"type": "object",
|
|
1604
|
+
"properties": {
|
|
1605
|
+
"href": {
|
|
1606
|
+
"type": "url",
|
|
1607
|
+
},
|
|
1608
|
+
"description": "LinkedStatus model"
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
```
|
|
1492
1613
|
|
|
1493
1614
|
### Relationships
|
|
1494
1615
|
|
data/RELEASING.md
CHANGED
|
@@ -16,7 +16,7 @@ Check that the last build succeeded in [Travis CI](https://travis-ci.org/ruby-gr
|
|
|
16
16
|
Change "Next" in [CHANGELOG.md](CHANGELOG.md) to the current date.
|
|
17
17
|
|
|
18
18
|
```
|
|
19
|
-
###
|
|
19
|
+
### 2.2.0 (2025-11-21)
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
Remove the lines with "Your contribution here.", since there will be no more contributions to this release.
|
|
@@ -25,7 +25,7 @@ Commit your changes.
|
|
|
25
25
|
|
|
26
26
|
```
|
|
27
27
|
git add CHANGELOG.md lib/grape-swagger/version.rb
|
|
28
|
-
git commit -m "Preparing for release,
|
|
28
|
+
git commit -m "Preparing for release, 2.2.0."
|
|
29
29
|
git push origin master
|
|
30
30
|
```
|
|
31
31
|
|
|
@@ -34,10 +34,10 @@ Release.
|
|
|
34
34
|
```
|
|
35
35
|
$ rake release
|
|
36
36
|
|
|
37
|
-
grape-swagger
|
|
38
|
-
Tagged
|
|
37
|
+
grape-swagger 2.2.0 built to pkg/grape-swagger-2.2.0.gem.
|
|
38
|
+
Tagged v2.2.0.
|
|
39
39
|
Pushed git commits and tags.
|
|
40
|
-
Pushed grape-swagger
|
|
40
|
+
Pushed grape-swagger 2.2.0 to rubygems.org.
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
### Prepare for the Next Version
|
|
@@ -47,7 +47,7 @@ Increment the minor version, the third number, modify [lib/grape-swagger/version
|
|
|
47
47
|
Add the next release to [CHANGELOG.md](CHANGELOG.md).
|
|
48
48
|
|
|
49
49
|
```
|
|
50
|
-
###
|
|
50
|
+
### 2.2.1 (Next)
|
|
51
51
|
|
|
52
52
|
#### Features
|
|
53
53
|
|
|
@@ -62,7 +62,7 @@ Commit your changes.
|
|
|
62
62
|
|
|
63
63
|
```
|
|
64
64
|
git add CHANGELOG.md lib/grape-swagger/version.rb
|
|
65
|
-
git commit -m "Preparing for next developer iteration,
|
|
65
|
+
git commit -m "Preparing for next developer iteration, 2.2.1."
|
|
66
66
|
git push origin master
|
|
67
67
|
```
|
|
68
68
|
|
|
@@ -71,7 +71,7 @@ git push origin master
|
|
|
71
71
|
Make an announcement on the [ruby-grape@googlegroups.com](mailto:ruby-grape@googlegroups.com) mailing list. The general format is as follows.
|
|
72
72
|
|
|
73
73
|
```
|
|
74
|
-
Grape-Swagger
|
|
74
|
+
Grape-Swagger 2.2.0 has been released.
|
|
75
75
|
|
|
76
76
|
There were 8 contributors to this release, not counting documentation.
|
|
77
77
|
|
data/grape-swagger.gemspec
CHANGED
|
@@ -15,8 +15,7 @@ Gem::Specification.new do |s|
|
|
|
15
15
|
s.metadata['rubygems_mfa_required'] = 'true'
|
|
16
16
|
|
|
17
17
|
s.required_ruby_version = '>= 3.1'
|
|
18
|
-
s.add_dependency 'grape', '>= 1.7', '<
|
|
19
|
-
s.add_dependency 'rack-test', '~> 2'
|
|
18
|
+
s.add_dependency 'grape', '>= 1.7', '< 4.0'
|
|
20
19
|
|
|
21
20
|
s.files = Dir['lib/**/*', '*.md', 'LICENSE.txt', 'grape-swagger.gemspec']
|
|
22
21
|
s.require_paths = ['lib']
|
|
@@ -7,7 +7,7 @@ module GrapeSwagger
|
|
|
7
7
|
def to_format(parameters)
|
|
8
8
|
parameters.reject { |parameter| parameter[:in] == 'body' }.each do |b|
|
|
9
9
|
related_parameters = parameters.select do |p|
|
|
10
|
-
p[:name] != b[:name] && p[:name].
|
|
10
|
+
p[:name] != b[:name] && p[:name].start_with?("#{b[:name].to_s.gsub(/\[\]\z/, '')}[")
|
|
11
11
|
end
|
|
12
12
|
parameters.reject! { |p| p[:name] == b[:name] } if move_down(b, related_parameters)
|
|
13
13
|
end
|
|
@@ -163,7 +163,7 @@ module GrapeSwagger
|
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
def prepare_nested_names(property, params)
|
|
166
|
-
params.each { |x| x[:name] = x[:name].sub(property, '').sub('[', '').sub(']', '') }
|
|
166
|
+
params.each { |x| x[:name] = x[:name].sub(property.to_s, '').sub('[', '').sub(']', '') }
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
def unify!(params)
|
|
@@ -141,8 +141,10 @@ module GrapeSwagger
|
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
def document_example(settings)
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
return unless settings.key?(:example)
|
|
145
|
+
|
|
146
|
+
key = @parsed_param[:in] == 'body' ? :example : :'x-example'
|
|
147
|
+
@parsed_param[key] = settings[:example]
|
|
146
148
|
end
|
|
147
149
|
|
|
148
150
|
def param_type(value_type, consumes)
|
|
@@ -11,7 +11,6 @@ require 'grape-swagger/doc_methods/path_string'
|
|
|
11
11
|
require 'grape-swagger/doc_methods/tag_name_description'
|
|
12
12
|
require 'grape-swagger/doc_methods/parse_params'
|
|
13
13
|
require 'grape-swagger/doc_methods/move_params'
|
|
14
|
-
require 'grape-swagger/doc_methods/headers'
|
|
15
14
|
require 'grape-swagger/doc_methods/build_model_definition'
|
|
16
15
|
require 'grape-swagger/doc_methods/version'
|
|
17
16
|
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
require 'active_support'
|
|
4
4
|
require 'active_support/core_ext/string/inflections'
|
|
5
|
-
|
|
5
|
+
require_relative 'request_param_parsers/headers'
|
|
6
|
+
require_relative 'request_param_parsers/route'
|
|
7
|
+
require_relative 'request_param_parsers/body'
|
|
8
|
+
require_relative 'token_owner_resolver'
|
|
6
9
|
|
|
7
10
|
module Grape
|
|
8
11
|
class Endpoint # rubocop:disable Metrics/ClassLength
|
|
@@ -12,9 +15,7 @@ module Grape
|
|
|
12
15
|
if content_types.empty?
|
|
13
16
|
formats = [target_class.format, target_class.default_format].compact.uniq
|
|
14
17
|
formats = GrapeSwagger::FORMATTER_DEFAULTS.keys if formats.empty?
|
|
15
|
-
content_types =
|
|
16
|
-
formats.include? content_type
|
|
17
|
-
end.values
|
|
18
|
+
content_types = formats.filter_map { |f| GrapeSwagger::CONTENT_TYPE_DEFAULTS[f] }
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
content_types.uniq
|
|
@@ -383,45 +384,15 @@ module Grape
|
|
|
383
384
|
end
|
|
384
385
|
|
|
385
386
|
def build_request_params(route, settings)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
def merge_params(route)
|
|
397
|
-
path_params = get_path_params(route.app&.inheritable_setting&.namespace_stackable)
|
|
398
|
-
param_keys = route.params.keys
|
|
399
|
-
|
|
400
|
-
# Merge path params options into route params
|
|
401
|
-
route_params = route.params
|
|
402
|
-
route_params.each_key do |key|
|
|
403
|
-
path = path_params[key] || {}
|
|
404
|
-
params = route_params[key]
|
|
405
|
-
params = {} unless params.is_a? Hash
|
|
406
|
-
route_params[key] = path.merge(params)
|
|
387
|
+
GrapeSwagger.request_param_parsers.each_with_object({}) do |parser_klass, accum|
|
|
388
|
+
params = parser_klass.parse(
|
|
389
|
+
route,
|
|
390
|
+
accum,
|
|
391
|
+
settings,
|
|
392
|
+
self
|
|
393
|
+
)
|
|
394
|
+
accum.merge!(params.stringify_keys)
|
|
407
395
|
end
|
|
408
|
-
|
|
409
|
-
route_params.delete_if { |key| key.is_a?(String) && param_keys.include?(key.to_sym) }.to_a
|
|
410
|
-
end
|
|
411
|
-
|
|
412
|
-
# Iterates over namespaces recursively
|
|
413
|
-
# to build a hash of path params with options, including type
|
|
414
|
-
def get_path_params(stackable_values)
|
|
415
|
-
params = {}
|
|
416
|
-
return param unless stackable_values
|
|
417
|
-
return params unless stackable_values.is_a? Grape::Util::StackableValues
|
|
418
|
-
|
|
419
|
-
stackable_values&.new_values&.dig(:namespace)&.each do |namespace| # rubocop:disable Style/SafeNavigationChainLength
|
|
420
|
-
space = namespace.space.to_s.gsub(':', '')
|
|
421
|
-
params[space] = namespace.options || {}
|
|
422
|
-
end
|
|
423
|
-
inherited_params = get_path_params(stackable_values.inherited_values)
|
|
424
|
-
inherited_params.merge(params)
|
|
425
396
|
end
|
|
426
397
|
|
|
427
398
|
def default_type(params)
|
|
@@ -469,7 +440,10 @@ module Grape
|
|
|
469
440
|
route_hidden = route.options[:hidden] if route.options.key?(:hidden)
|
|
470
441
|
return route_hidden unless route_hidden.is_a?(Proc)
|
|
471
442
|
|
|
472
|
-
|
|
443
|
+
return route_hidden.call unless options[:token_owner]
|
|
444
|
+
|
|
445
|
+
token_owner = GrapeSwagger::TokenOwnerResolver.resolve(self, options[:token_owner])
|
|
446
|
+
GrapeSwagger::TokenOwnerResolver.evaluate_proc(route_hidden, token_owner)
|
|
473
447
|
end
|
|
474
448
|
|
|
475
449
|
def hidden_parameter?(value)
|
data/lib/grape-swagger/errors.rb
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'request_param_parsers/headers'
|
|
4
|
+
require_relative 'request_param_parsers/route'
|
|
5
|
+
require_relative 'request_param_parsers/body'
|
|
6
|
+
|
|
7
|
+
module GrapeSwagger
|
|
8
|
+
class RequestParamParserRegistry
|
|
9
|
+
DEFAULT_PARSERS = [
|
|
10
|
+
GrapeSwagger::RequestParamParsers::Headers,
|
|
11
|
+
GrapeSwagger::RequestParamParsers::Route,
|
|
12
|
+
GrapeSwagger::RequestParamParsers::Body
|
|
13
|
+
].freeze
|
|
14
|
+
|
|
15
|
+
include Enumerable
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
@parsers = DEFAULT_PARSERS.dup
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def register(klass)
|
|
22
|
+
remove_parser(klass)
|
|
23
|
+
@parsers << klass
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def insert_before(before_klass, klass)
|
|
27
|
+
remove_parser(klass)
|
|
28
|
+
insert_at = @parsers.index(before_klass) || @parsers.size
|
|
29
|
+
@parsers.insert(insert_at, klass)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def insert_after(after_klass, klass)
|
|
33
|
+
remove_parser(klass)
|
|
34
|
+
insert_at = @parsers.index(after_klass)
|
|
35
|
+
@parsers.insert(insert_at ? insert_at + 1 : @parsers.size, klass)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def each(&)
|
|
39
|
+
@parsers.each(&)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def remove_parser(klass)
|
|
45
|
+
@parsers.reject! { |k| k == klass }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module GrapeSwagger
|
|
4
|
-
module
|
|
5
|
-
class
|
|
6
|
-
attr_reader :params, :settings, :endpoint
|
|
4
|
+
module RequestParamParsers
|
|
5
|
+
class Body
|
|
6
|
+
attr_reader :route, :params, :settings, :endpoint
|
|
7
7
|
|
|
8
|
-
def self.
|
|
9
|
-
new(params, settings, endpoint).
|
|
8
|
+
def self.parse(route, params, settings, endpoint)
|
|
9
|
+
new(route, params, settings, endpoint).parse
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def initialize(params, settings, endpoint)
|
|
12
|
+
def initialize(_route, params, settings, endpoint)
|
|
13
13
|
@params = params
|
|
14
14
|
@settings = settings
|
|
15
15
|
@endpoint = endpoint
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def
|
|
18
|
+
def parse
|
|
19
19
|
public_params.each_with_object({}) do |(name, options), memo|
|
|
20
20
|
name = name.to_s
|
|
21
|
-
param_type = options[:type]
|
|
22
|
-
param_type = param_type.to_s unless param_type.nil?
|
|
21
|
+
param_type = options[:type]&.to_s
|
|
23
22
|
|
|
24
|
-
if
|
|
23
|
+
if array_param?(param_type)
|
|
25
24
|
options[:is_array] = true
|
|
26
25
|
name += '[]' if array_use_braces?
|
|
27
26
|
end
|
|
@@ -36,8 +35,8 @@ module GrapeSwagger
|
|
|
36
35
|
@array_use_braces ||= settings[:array_use_braces] && !includes_body_param?
|
|
37
36
|
end
|
|
38
37
|
|
|
39
|
-
def
|
|
40
|
-
return false
|
|
38
|
+
def array_param?(param_type)
|
|
39
|
+
return false if param_type.nil?
|
|
41
40
|
return true if param_type == 'Array'
|
|
42
41
|
|
|
43
42
|
param_types = param_type.match(/\[(.*)\]$/)
|
|
@@ -48,21 +47,14 @@ module GrapeSwagger
|
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
def public_params
|
|
51
|
-
params.select { |param| public_parameter?(param) }
|
|
50
|
+
params.select { |_key, param| public_parameter?(param) }
|
|
52
51
|
end
|
|
53
52
|
|
|
54
|
-
def public_parameter?(
|
|
55
|
-
param_options = param.last
|
|
53
|
+
def public_parameter?(param_options)
|
|
56
54
|
return true unless param_options.key?(:documentation) && !param_options[:required]
|
|
57
55
|
|
|
58
56
|
param_hidden = param_options[:documentation].fetch(:hidden, false)
|
|
59
|
-
if param_hidden.is_a?(Proc)
|
|
60
|
-
param_hidden = if settings[:token_owner]
|
|
61
|
-
param_hidden.call(endpoint.send(settings[:token_owner].to_sym))
|
|
62
|
-
else
|
|
63
|
-
param_hidden.call
|
|
64
|
-
end
|
|
65
|
-
end
|
|
57
|
+
param_hidden = evaluate_hidden_proc(param_hidden) if param_hidden.is_a?(Proc)
|
|
66
58
|
!param_hidden
|
|
67
59
|
end
|
|
68
60
|
|
|
@@ -71,6 +63,13 @@ module GrapeSwagger
|
|
|
71
63
|
options.dig(:documentation, :param_type) == 'body' || options.dig(:documentation, :in) == 'body'
|
|
72
64
|
end
|
|
73
65
|
end
|
|
66
|
+
|
|
67
|
+
def evaluate_hidden_proc(hidden_proc)
|
|
68
|
+
return hidden_proc.call unless settings[:token_owner]
|
|
69
|
+
|
|
70
|
+
token_owner = GrapeSwagger::TokenOwnerResolver.resolve(endpoint, settings[:token_owner])
|
|
71
|
+
GrapeSwagger::TokenOwnerResolver.evaluate_proc(hidden_proc, token_owner)
|
|
72
|
+
end
|
|
74
73
|
end
|
|
75
74
|
end
|
|
76
75
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GrapeSwagger
|
|
4
|
+
module RequestParamParsers
|
|
5
|
+
class Headers
|
|
6
|
+
attr_reader :route
|
|
7
|
+
|
|
8
|
+
def self.parse(route, params, settings, endpoint)
|
|
9
|
+
new(route, params, settings, endpoint).parse
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(route, _params, _settings, _endpoint)
|
|
13
|
+
@route = route
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def parse
|
|
17
|
+
return {} unless route.headers
|
|
18
|
+
|
|
19
|
+
route.headers.each_with_object({}) do |(name, definition), accum|
|
|
20
|
+
# Extract the description from any key type (string or symbol)
|
|
21
|
+
description = definition[:description] || definition['description']
|
|
22
|
+
doc = { desc: description, in: 'header' }
|
|
23
|
+
|
|
24
|
+
header_attrs = definition.symbolize_keys.except(:description, 'description')
|
|
25
|
+
header_attrs[:type] = definition[:type].titleize if definition[:type]
|
|
26
|
+
header_attrs[:documentation] = doc
|
|
27
|
+
|
|
28
|
+
accum[name] = header_attrs
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GrapeSwagger
|
|
4
|
+
module RequestParamParsers
|
|
5
|
+
class Route
|
|
6
|
+
DEFAULT_PARAM_TYPE = { required: true, type: 'Integer' }.freeze
|
|
7
|
+
|
|
8
|
+
attr_reader :route
|
|
9
|
+
|
|
10
|
+
def self.parse(route, params, settings, endpoint)
|
|
11
|
+
new(route, params, settings, endpoint).parse
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(route, _params, _settings, _endpoint)
|
|
15
|
+
@route = route
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parse
|
|
19
|
+
stackable_values = route.app&.inheritable_setting&.namespace_stackable
|
|
20
|
+
|
|
21
|
+
path_params = build_path_params(stackable_values)
|
|
22
|
+
|
|
23
|
+
fulfill_params(path_params)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def build_path_params(stackable_values)
|
|
29
|
+
params = {}
|
|
30
|
+
|
|
31
|
+
while stackable_values.is_a?(Grape::Util::StackableValues)
|
|
32
|
+
params.merge!(fetch_inherited_params(stackable_values))
|
|
33
|
+
stackable_values = stackable_values.inherited_values
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
params
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def fetch_inherited_params(stackable_values)
|
|
40
|
+
return {} unless stackable_values.new_values
|
|
41
|
+
|
|
42
|
+
namespaces = stackable_values.new_values[:namespace] || []
|
|
43
|
+
|
|
44
|
+
namespaces.each_with_object({}) do |namespace, params|
|
|
45
|
+
space = namespace.space.to_s.gsub(':', '')
|
|
46
|
+
params[space] = namespace.options || {}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def fulfill_params(path_params)
|
|
51
|
+
# Merge path params options into route params
|
|
52
|
+
route.params.each_with_object({}) do |(param, definition), accum|
|
|
53
|
+
# The route.params hash includes both parametrized params (with a string as a key)
|
|
54
|
+
# and well-defined params from body/query (with a symbol as a key).
|
|
55
|
+
# We avoid overriding well-defined params with parametrized ones.
|
|
56
|
+
key = param.is_a?(String) ? param.to_sym : param
|
|
57
|
+
next if param.is_a?(String) && accum.key?(key)
|
|
58
|
+
|
|
59
|
+
defined_options = definition.is_a?(Hash) ? definition : {}
|
|
60
|
+
value = (path_params[param] || {}).merge(defined_options)
|
|
61
|
+
accum[key] = value.empty? ? DEFAULT_PARAM_TYPE : value
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|