grape-swagger 0.23.0 → 0.24.0
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/.rubocop_todo.yml +1 -1
- data/CHANGELOG.md +20 -2
- data/Dangerfile +1 -1
- data/Gemfile +5 -1
- data/README.md +172 -5
- data/lib/grape-swagger.rb +9 -1
- data/lib/grape-swagger/doc_methods.rb +22 -29
- data/lib/grape-swagger/doc_methods/parse_params.rb +2 -0
- data/lib/grape-swagger/endpoint.rb +29 -10
- data/lib/grape-swagger/rake/oapi_tasks.rb +99 -0
- data/lib/grape-swagger/version.rb +1 -1
- data/spec/issues/430_entity_definitions_spec.rb +48 -0
- data/spec/lib/oapi_tasks_spec.rb +133 -0
- data/spec/swagger_v2/api_swagger_v2_body_definitions_spec.rb +2 -0
- data/spec/swagger_v2/description_not_initialized.rb +0 -2
- data/spec/swagger_v2/guarded_endpoint_spec.rb +116 -0
- data/spec/swagger_v2/host.rb +0 -2
- data/spec/swagger_v2/namespaced_api_spec.rb +52 -0
- data/spec/swagger_v2/params_array_collection_fromat_spec.rb +80 -0
- data/spec/swagger_v2/security_requirement_spec.rb +23 -0
- metadata +14 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99ac4d378547c6998e6c712a83eb82d8277786fb
|
4
|
+
data.tar.gz: 9d18548301ad46bd474671a770c5e528ee7a4f3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b609366f8b1e964dbffbc0a65593bca55d050ac46cac23896627fd0b2b49f9a2b4fc368022e20d3e2866d458322d083a13f1bc44d7cc36c4bff323d7082497ed
|
7
|
+
data.tar.gz: 6c6e93549bf4b7eebc659155dcb21ce5d999ef811ea1f8dbceb7c6104b35c3765d0ea6ef16fb706303f9dcd86c99811862fd939af471cbb1a5ff730c9c07aa50
|
data/.rubocop_todo.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -8,12 +8,30 @@
|
|
8
8
|
|
9
9
|
* Your contribution here.
|
10
10
|
|
11
|
+
### 0.24.0 (September 23, 2016)
|
12
|
+
|
13
|
+
#### Features
|
14
|
+
|
15
|
+
* [#504](https://github.com/ruby-grape/grape-swagger/pull/504): Added support for set the 'collectionFormat' of arrays - [@rczjns](https://github.com/rczjns).
|
16
|
+
* [#502](https://github.com/ruby-grape/grape-swagger/pull/502): Adds specs for rake tasks - [@LeFnord](https://github.com/LeFnord).
|
17
|
+
* [#501](https://github.com/ruby-grape/grape-swagger/pull/501): Adds getting of a specified resource for Rake Tasks - [@LeFnord](https://github.com/LeFnord).
|
18
|
+
* [#500](https://github.com/ruby-grape/grape-swagger/pull/500): Adds Rake tasks to get and validate OAPI/Swagger documentation - [@LeFnord](https://github.com/LeFnord).
|
19
|
+
* [#493](https://github.com/ruby-grape/grape-swagger/pull/493): Swagger UI endpoint authorization. - [@texpert](https://github.com/texpert).
|
20
|
+
* [#492](https://github.com/ruby-grape/grape/pull/492): Define security requirements on endpoint methods - [@tomregelink](https://github.com/tomregelink).
|
21
|
+
* [#497](https://github.com/ruby-grape/grape-swagger/pull/497): Use ruby-grape-danger in Dangerfile - [@dblock](https://github.com/dblock).
|
22
|
+
|
23
|
+
#### Fixes
|
24
|
+
|
25
|
+
* [#503](https://github.com/ruby-grape/grape-swagger/pull/503): Corrects exposing of inline definitions - [@LeFnord](https://github.com/LeFnord).
|
26
|
+
* [#494](https://github.com/ruby-grape/grape-swagger/pull/494): Header parametes are now included in documentation when body parameters have been defined - [@anakinj](https://github.com/anakinj).
|
27
|
+
* [#505](https://github.com/ruby-grape/grape-swagger/pull/505): Combines namespaces with their mounted paths to allow APIs with specified mount_paths - [@KevinLiddle](https://github.com/KevinLiddle).
|
28
|
+
|
11
29
|
### 0.23.0 (August 5, 2016)
|
12
30
|
|
13
31
|
#### Features
|
14
32
|
|
15
|
-
* [#491](https://github.com/ruby-grape/grape/pull/491): Add `ignore_defaults` option - [@pezholio](https://github.com/pezholio).
|
16
|
-
* [#486](https://github.com/ruby-grape/grape/pull/486): Use an automated PR linter, [danger.systems](http://danger.systems) - [@dblock](https://github.com/dblock).
|
33
|
+
* [#491](https://github.com/ruby-grape/grape-swagger/pull/491): Add `ignore_defaults` option - [@pezholio](https://github.com/pezholio).
|
34
|
+
* [#486](https://github.com/ruby-grape/grape-swagger/pull/486): Use an automated PR linter, [danger.systems](http://danger.systems) - [@dblock](https://github.com/dblock).
|
17
35
|
|
18
36
|
#### Fixes
|
19
37
|
|
data/Dangerfile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
danger.import_dangerfile(gem: 'ruby-grape-danger')
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -14,10 +14,12 @@
|
|
14
14
|
* [Model Parsers](#model_parsers)
|
15
15
|
* [Configure](#configure)
|
16
16
|
* [Routes Configuration](#routes)
|
17
|
+
* [Securing the Swagger UI](#oauth)
|
17
18
|
* [Markdown](#md_usage)
|
18
19
|
* [Response documentation](#response)
|
19
20
|
* [Extensions](#extensions)
|
20
21
|
* [Example](#example)
|
22
|
+
* [Rake Tasks](#rake)
|
21
23
|
|
22
24
|
<a name="what" />
|
23
25
|
## What is grape-swagger?
|
@@ -50,7 +52,7 @@ grape-swagger | swagger spec | grape | grape-entity | represen
|
|
50
52
|
0.20.1 | 2.0 | >= 0.12.0 ... <= 0.14.0 | <= 0.5.1 | n/a |
|
51
53
|
0.20.3 | 2.0 | >= 0.12.0 ... ~> 0.16.2 | ~> 0.5.1 | n/a |
|
52
54
|
0.21.0 | 2.0 | >= 0.12.0 ... <= 0.16.2 | <= 0.5.1 | >= 2.4.1 |
|
53
|
-
0.
|
55
|
+
0.23.0 | 2.0 | >= 0.12.0 ... <= 0.17.0 | <= 0.5.1 | >= 2.4.1 |
|
54
56
|
|
55
57
|
<a name="swagger-spec" />
|
56
58
|
## Swagger-Spec
|
@@ -192,6 +194,9 @@ end
|
|
192
194
|
* [add_version](#add_version)
|
193
195
|
* [doc_version](#doc_version)
|
194
196
|
* [markdown](#markdown)
|
197
|
+
* [endpoint_auth_wrapper](#endpoint_auth_wrapper)
|
198
|
+
* [swagger_endpoint_guard](#swagger_endpoint_guard)
|
199
|
+
* [oauth_token](#oauth_token)
|
195
200
|
* [security_definitions](#security_definitions)
|
196
201
|
* [models](#models)
|
197
202
|
* [hide_documentation_path](#hide_documentation_path)
|
@@ -273,6 +278,33 @@ add_swagger_documentation \
|
|
273
278
|
markdown: GrapeSwagger::Markdown::RedcarpetAdapter.new
|
274
279
|
```
|
275
280
|
|
281
|
+
<a name="endpoint_auth_wrapper" />
|
282
|
+
#### endpoint_auth_wrapper:
|
283
|
+
Specify the middleware to use for securing endpoints.
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
add_swagger_documentation \
|
287
|
+
endpoint_auth_wrapper: WineBouncer::OAuth2
|
288
|
+
```
|
289
|
+
|
290
|
+
<a name="swagger_endpoint_guard" />
|
291
|
+
#### swagger_endpoint_guard:
|
292
|
+
Specify the method and auth scopes, used by the middleware for securing endpoints.
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
add_swagger_documentation \
|
296
|
+
swagger_endpoint_guard: 'oauth2 false'
|
297
|
+
```
|
298
|
+
|
299
|
+
<a name="oauth_token" />
|
300
|
+
#### oauth_token:
|
301
|
+
Specify the method to get the oauth_token, provided by the middleware.
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
add_swagger_documentation \
|
305
|
+
oauth_token: 'doorkeeper_access_token'
|
306
|
+
```
|
307
|
+
|
276
308
|
<a name="security_definitions" />
|
277
309
|
#### security_definitions:
|
278
310
|
Specify the [Security Definitions Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object)
|
@@ -518,6 +550,39 @@ end
|
|
518
550
|
}
|
519
551
|
```
|
520
552
|
|
553
|
+
#### Collection format of arrays
|
554
|
+
|
555
|
+
You can set the collection format of an array, using the documentation hash.
|
556
|
+
|
557
|
+
Collection format determines the format of the array if type array is used. Possible values are:
|
558
|
+
* csv - comma separated values foo,bar.
|
559
|
+
* ssv - space separated values foo bar.
|
560
|
+
* tsv - tab separated values foo\tbar.
|
561
|
+
* pipes - pipe separated values foo|bar.
|
562
|
+
* multi - corresponds to multiple parameter instances instead of multiple values for a single instance foo=bar&foo=baz. This is valid only for parameters in "query" or "formData".
|
563
|
+
|
564
|
+
```ruby
|
565
|
+
params do
|
566
|
+
requires :statuses, type: Array[String], documentation: { collectionFormat: 'multi' }
|
567
|
+
end
|
568
|
+
post :act do
|
569
|
+
...
|
570
|
+
end
|
571
|
+
```
|
572
|
+
|
573
|
+
```json
|
574
|
+
{
|
575
|
+
"in": "formData",
|
576
|
+
"name": "statuses",
|
577
|
+
"type": "array",
|
578
|
+
"items": {
|
579
|
+
"type": "string"
|
580
|
+
},
|
581
|
+
"collectionFormat": "multi",
|
582
|
+
"required": true
|
583
|
+
}
|
584
|
+
```
|
585
|
+
|
521
586
|
#### Multi types
|
522
587
|
|
523
588
|
By default when you set multi types, the first type is selected as swagger type
|
@@ -765,9 +830,78 @@ module API
|
|
765
830
|
end
|
766
831
|
```
|
767
832
|
|
833
|
+
<a name="oauth" />
|
834
|
+
## Securing the Swagger UI
|
835
|
+
|
836
|
+
|
837
|
+
The Swagger UI on Grape could be secured from unauthorized access using any middleware, which provides certain methods:
|
838
|
+
|
839
|
+
- a *before* method to be run in the Grape controller for authorization purpose;
|
840
|
+
- some guard method, which could receive as argument a string or an array of authorization scopes;
|
841
|
+
- a method which processes and returns the access token received in the HTTP request headers (usually in the 'HTTP_AUTHORIZATION' header).
|
842
|
+
|
843
|
+
Below are some examples of securing the Swagger UI on Grape installed along with Ruby on Rails:
|
844
|
+
|
845
|
+
- The WineBouncer and Doorkeeper gems are used in the examples;
|
846
|
+
- 'rails' and 'wine_bouncer' gems should be required prior to 'grape-swagger' in boot.rb;
|
847
|
+
- This works with a fresh PR to WineBouncer which is yet unmerged - [WineBouncer PR](https://github.com/antek-drzewiecki/wine_bouncer/pull/64).
|
848
|
+
|
849
|
+
This is how to configure the grape_swagger documentation:
|
850
|
+
|
851
|
+
```ruby
|
852
|
+
add_swagger_documentation base_path: '/',
|
853
|
+
title: 'My API',
|
854
|
+
doc_version: '0.0.1',
|
855
|
+
hide_documentation_path: true,
|
856
|
+
hide_format: true,
|
857
|
+
endpoint_auth_wrapper: WineBouncer::OAuth2, # This is the middleware for securing the Swagger UI
|
858
|
+
swagger_endpoint_guard: 'oauth2 false', # this is the guard method and scope
|
859
|
+
oauth_token: 'doorkeeper_access_token' # This is the method returning the access_token
|
860
|
+
```
|
861
|
+
|
862
|
+
The guard method should inject the Security Requirement Object into the endpoint's route settings (see Grape::DSL::Settings.route_setting method).
|
863
|
+
|
864
|
+
The 'oauth2 false' added to swagger_documentation is making the main Swagger endpoint protected with OAuth, i.e. it
|
865
|
+
is retreiving the access_token from the HTTP request, but the 'false' scope is for skipping authorization and showing
|
866
|
+
the UI for everyone. If the scope would be set to something else, like 'oauth2 admin', for example, than the UI
|
867
|
+
wouldn't be displayed at all to unauthorized users.
|
868
|
+
|
869
|
+
Further on, the guard could be used, where necessary, for endpoint access protection. Put it prior to the endpoint's method:
|
870
|
+
|
871
|
+
```ruby
|
872
|
+
resource :users do
|
873
|
+
oauth2 'read, write'
|
874
|
+
get do
|
875
|
+
render_users
|
876
|
+
end
|
877
|
+
|
878
|
+
oauth2 'admin'
|
879
|
+
post do
|
880
|
+
User.create!...
|
881
|
+
end
|
882
|
+
end
|
883
|
+
```
|
884
|
+
|
885
|
+
And, finally, if you want to not only restrict the access, but to completely hide the endpoint from unauthorized
|
886
|
+
users, you could pass a lambda to the :hidden key of a endpoint's description:
|
887
|
+
|
888
|
+
```ruby
|
889
|
+
not_admins = lambda { |token=nil| token.nil? || !User.find(token.resource_owner_id).admin? }
|
890
|
+
|
891
|
+
resource :users do
|
892
|
+
desc 'Create user', hidden: not_admins
|
893
|
+
oauth2 'admin'
|
894
|
+
post do
|
895
|
+
User.create!...
|
896
|
+
end
|
897
|
+
end
|
898
|
+
```
|
899
|
+
|
900
|
+
The lambda is checking whether the user is authenticated (if not, the token is nil by default), and has the admin
|
901
|
+
role - only admins can see this endpoint.
|
768
902
|
|
769
903
|
<a name="md_usage" />
|
770
|
-
|
904
|
+
## Markdown in Detail
|
771
905
|
|
772
906
|
The grape-swagger gem allows you to add an explanation in markdown in the detail field. Which would result in proper formatted markdown in Swagger UI.
|
773
907
|
Grape-swagger uses adapters for several markdown formatters. It includes adapters for [kramdown](http://kramdown.rubyforge.org) (kramdown [syntax](http://kramdown.rubyforge.org/syntax.html)) and [redcarpet](https://github.com/vmg/redcarpet).
|
@@ -961,19 +1095,20 @@ route_setting :x_def, [{ for: 422, other: 'stuff' }, { for: 200, some: 'stuff' }
|
|
961
1095
|
```
|
962
1096
|
|
963
1097
|
<a="example" />
|
964
|
-
|
1098
|
+
## Example
|
965
1099
|
|
966
1100
|
Go into example directory and run it: `$ bundle exec rackup`
|
967
1101
|
go to: `http://localhost:9292/swagger_doc` to get it
|
968
1102
|
|
969
1103
|
For request examples load the [postman file]()
|
970
|
-
|
1104
|
+
|
1105
|
+
#### Grouping the API list using Namespace
|
971
1106
|
|
972
1107
|
Use namespace for grouping APIs
|
973
1108
|
|
974
1109
|

|
975
1110
|
|
976
|
-
|
1111
|
+
#### Example Code
|
977
1112
|
|
978
1113
|
```ruby
|
979
1114
|
class NamespaceApi < Grape::API
|
@@ -1005,6 +1140,38 @@ end
|
|
1005
1140
|
|
1006
1141
|
```
|
1007
1142
|
|
1143
|
+
|
1144
|
+
<a name="rake" />
|
1145
|
+
## Rake Tasks
|
1146
|
+
|
1147
|
+
Add these lines to your Rakefile, and initialize the Task class with your Api class – be sure your Api class is available.
|
1148
|
+
|
1149
|
+
```ruby
|
1150
|
+
require 'grape-swagger/rake/oapi_tasks'
|
1151
|
+
GrapeSwagger::Rake::OapiTasks.new(::Api::Base)
|
1152
|
+
```
|
1153
|
+
|
1154
|
+
#### OpenApi/Swagger Documentation
|
1155
|
+
|
1156
|
+
```
|
1157
|
+
rake oapi:fetch
|
1158
|
+
params:
|
1159
|
+
- store={ true | file_name } – save as JSON (optional)
|
1160
|
+
- resource=resource_name – get only for this one (optional)
|
1161
|
+
```
|
1162
|
+
|
1163
|
+
#### OpenApi/Swagger Validation
|
1164
|
+
|
1165
|
+
**requires**: `npm` and `swagger-cli` to be installed
|
1166
|
+
|
1167
|
+
|
1168
|
+
```
|
1169
|
+
rake oapi:validate
|
1170
|
+
params:
|
1171
|
+
- resource=resource_name – get only for this one (optional)
|
1172
|
+
```
|
1173
|
+
|
1174
|
+
|
1008
1175
|
## Contributing to grape-swagger
|
1009
1176
|
|
1010
1177
|
See [CONTRIBUTING](CONTRIBUTING.md).
|
data/lib/grape-swagger.rb
CHANGED
@@ -18,6 +18,7 @@ module GrapeSwagger
|
|
18
18
|
@model_parsers ||= GrapeSwagger::ModelParsers.new
|
19
19
|
end
|
20
20
|
end
|
21
|
+
autoload :Rake, 'grape-swagger/rake/oapi_tasks'
|
21
22
|
end
|
22
23
|
|
23
24
|
module Grape
|
@@ -31,6 +32,11 @@ module Grape
|
|
31
32
|
version_for(options)
|
32
33
|
options = { target_class: self }.merge(options)
|
33
34
|
@target_class = options[:target_class]
|
35
|
+
auth_wrapper = options[:endpoint_auth_wrapper]
|
36
|
+
|
37
|
+
if auth_wrapper && auth_wrapper.method_defined?(:before) && !middleware.flatten.include?(auth_wrapper)
|
38
|
+
use auth_wrapper
|
39
|
+
end
|
34
40
|
|
35
41
|
documentation_class.setup(options)
|
36
42
|
mount(documentation_class)
|
@@ -80,7 +86,9 @@ module Grape
|
|
80
86
|
end
|
81
87
|
# use the full namespace here (not the latest level only)
|
82
88
|
# and strip leading slash
|
83
|
-
|
89
|
+
mount_path = (endpoint.namespace_stackable(:mount_path) || []).join('/')
|
90
|
+
full_namespace = (mount_path + endpoint.namespace).sub(/\/{2,}/, '/').sub(/^\//, '')
|
91
|
+
@target_class.combined_namespaces[full_namespace] = ns if ns
|
84
92
|
|
85
93
|
combine_namespaces(endpoint.options[:app]) if endpoint.options[:app]
|
86
94
|
end
|
@@ -31,37 +31,38 @@ module GrapeSwagger
|
|
31
31
|
# options could be set on #add_swagger_documentation call,
|
32
32
|
# for available options see #defaults
|
33
33
|
target_class = options[:target_class]
|
34
|
-
|
35
|
-
|
34
|
+
guard = options[:swagger_endpoint_guard]
|
35
|
+
formatter = options[:format]
|
36
36
|
|
37
37
|
class_variables_from(options)
|
38
38
|
|
39
39
|
[:format, :default_format, :default_error_formatter].each do |method|
|
40
|
-
send(method,
|
41
|
-
end if
|
42
|
-
# getting of the whole swagger2.0 spec file
|
43
|
-
desc api_doc.delete(:desc), api_doc
|
44
|
-
get mount_path do
|
45
|
-
header['Access-Control-Allow-Origin'] = '*'
|
46
|
-
header['Access-Control-Request-Method'] = '*'
|
40
|
+
send(method, formatter)
|
41
|
+
end if formatter
|
47
42
|
|
48
|
-
|
43
|
+
send(guard.split.first.to_sym, *guard.split(/[\s,]+/).drop(1)) unless guard.nil?
|
44
|
+
|
45
|
+
output_path_definitions = proc do |combi_routes, endpoint|
|
46
|
+
output = endpoint.swagger_object(
|
49
47
|
target_class,
|
50
|
-
request,
|
48
|
+
endpoint.request,
|
51
49
|
options
|
52
50
|
)
|
53
51
|
|
54
|
-
|
55
|
-
paths, definitions = path_and_definition_objects(target_routes, options)
|
52
|
+
paths, definitions = endpoint.path_and_definition_objects(combi_routes, options)
|
56
53
|
output[:paths] = paths unless paths.blank?
|
57
54
|
output[:definitions] = definitions unless definitions.blank?
|
58
55
|
|
59
56
|
output
|
60
57
|
end
|
61
58
|
|
62
|
-
|
63
|
-
|
64
|
-
|
59
|
+
get mount_path do
|
60
|
+
header['Access-Control-Allow-Origin'] = '*'
|
61
|
+
header['Access-Control-Request-Method'] = '*'
|
62
|
+
|
63
|
+
output_path_definitions.call(target_class.combined_namespace_routes, self)
|
64
|
+
end
|
65
|
+
|
65
66
|
params do
|
66
67
|
requires :name, type: String, desc: 'Resource name of mounted API'
|
67
68
|
optional :locale, type: Symbol, desc: 'Locale of API documentation'
|
@@ -72,18 +73,7 @@ module GrapeSwagger
|
|
72
73
|
combined_routes = target_class.combined_namespace_routes[params[:name]]
|
73
74
|
error!({ error: 'named resource not exist' }, 400) if combined_routes.nil?
|
74
75
|
|
75
|
-
|
76
|
-
target_class,
|
77
|
-
request,
|
78
|
-
options
|
79
|
-
)
|
80
|
-
|
81
|
-
target_routes = { params[:name] => combined_routes }
|
82
|
-
paths, definitions = path_and_definition_objects(target_routes, options)
|
83
|
-
output[:paths] = paths unless paths.blank?
|
84
|
-
output[:definitions] = definitions unless definitions.blank?
|
85
|
-
|
86
|
-
output
|
76
|
+
output_path_definitions.call({ params[:name] => combined_routes }, self)
|
87
77
|
end
|
88
78
|
end
|
89
79
|
|
@@ -104,7 +94,10 @@ module GrapeSwagger
|
|
104
94
|
authorizations: nil,
|
105
95
|
security_definitions: nil,
|
106
96
|
api_documentation: { desc: 'Swagger compatible API description' },
|
107
|
-
specific_api_documentation: { desc: 'Swagger compatible API description for specific API' }
|
97
|
+
specific_api_documentation: { desc: 'Swagger compatible API description for specific API' },
|
98
|
+
endpoint_auth_wrapper: nil,
|
99
|
+
swagger_endpoint_guard: nil,
|
100
|
+
oauth_token: nil
|
108
101
|
}
|
109
102
|
end
|
110
103
|
|
@@ -66,6 +66,7 @@ module GrapeSwagger
|
|
66
66
|
param_type = value_type[:documentation][:param_type]
|
67
67
|
doc_type = value_type[:documentation][:type]
|
68
68
|
type = GrapeSwagger::DocMethods::DataType.mapping(doc_type) if doc_type && !DataType.request_primitive?(doc_type)
|
69
|
+
collection_format = value_type[:documentation][:collectionFormat]
|
69
70
|
end
|
70
71
|
|
71
72
|
array_items = {
|
@@ -76,6 +77,7 @@ module GrapeSwagger
|
|
76
77
|
@parsed_param[:in] = param_type || 'formData'
|
77
78
|
@parsed_param[:items] = array_items
|
78
79
|
@parsed_param[:type] = 'array'
|
80
|
+
@parsed_param[:collectionFormat] = collection_format if %w(csv ssv tsv pipes multi).include?(collection_format)
|
79
81
|
end
|
80
82
|
end
|
81
83
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support'
|
2
4
|
require 'active_support/core_ext/string/inflections.rb'
|
3
5
|
|
@@ -84,7 +86,7 @@ module Grape
|
|
84
86
|
# path object
|
85
87
|
def path_item(routes, options)
|
86
88
|
routes.each do |route|
|
87
|
-
next if hidden?(route)
|
89
|
+
next if hidden?(route, options)
|
88
90
|
|
89
91
|
@item, path = GrapeSwagger::DocMethods::PathString.build(route, options)
|
90
92
|
@entity = route.entity || route.options[:success]
|
@@ -108,6 +110,7 @@ module Grape
|
|
108
110
|
method[:produces] = produces_object(route, options[:produces] || options[:format])
|
109
111
|
method[:consumes] = consumes_object(route, options[:format])
|
110
112
|
method[:parameters] = params_object(route)
|
113
|
+
method[:security] = security_object(route)
|
111
114
|
method[:responses] = response_object(route, options[:markdown])
|
112
115
|
method[:tags] = tag_object(route)
|
113
116
|
method[:operationId] = GrapeSwagger::DocMethods::OperationId.build(route, path)
|
@@ -116,6 +119,10 @@ module Grape
|
|
116
119
|
[route.request_method.downcase.to_sym, method]
|
117
120
|
end
|
118
121
|
|
122
|
+
def security_object(route)
|
123
|
+
route.options[:security] if route.options.key?(:security)
|
124
|
+
end
|
125
|
+
|
119
126
|
def summary_object(route)
|
120
127
|
summary = route.options[:desc] if route.options.key?(:desc)
|
121
128
|
summary = route.description if route.description.present?
|
@@ -215,15 +222,17 @@ module Grape
|
|
215
222
|
declared_params = route.settings[:declared_params] if route.settings[:declared_params].present?
|
216
223
|
required, exposed = route.params.partition { |x| x.first.is_a? String }
|
217
224
|
required = GrapeSwagger::DocMethods::Headers.parse(route) + required unless route.headers.nil?
|
225
|
+
|
218
226
|
default_type(required)
|
219
227
|
default_type(exposed)
|
220
228
|
|
221
|
-
unless declared_params.nil? && route.headers.nil?
|
222
|
-
|
223
|
-
|
229
|
+
request_params = unless declared_params.nil? && route.headers.nil?
|
230
|
+
parse_request_params(required)
|
231
|
+
end || {}
|
232
|
+
|
233
|
+
request_params = route.params.merge(request_params) if route.params.present? && !route.settings[:declared_params].present?
|
224
234
|
|
225
|
-
|
226
|
-
request_params || {}
|
235
|
+
request_params
|
227
236
|
end
|
228
237
|
|
229
238
|
def default_type(params)
|
@@ -279,13 +288,23 @@ module Grape
|
|
279
288
|
end
|
280
289
|
|
281
290
|
def model_name(name)
|
282
|
-
name.respond_to?(:
|
291
|
+
if name.respond_to?(:entity_name)
|
292
|
+
name.entity_name
|
293
|
+
elsif name.to_s.end_with?('Entity', 'Entities')
|
294
|
+
length = 0
|
295
|
+
name.to_s.split('::')[0..-2].reverse.take_while do |x|
|
296
|
+
length += x.length
|
297
|
+
length < 42
|
298
|
+
end.reverse.join
|
299
|
+
else
|
300
|
+
name.name.demodulize.camelize
|
301
|
+
end
|
283
302
|
end
|
284
303
|
|
285
|
-
def hidden?(route)
|
304
|
+
def hidden?(route, options)
|
286
305
|
route_hidden = route.options[:hidden]
|
287
|
-
|
288
|
-
route_hidden
|
306
|
+
return route_hidden unless route_hidden.is_a?(Proc)
|
307
|
+
options[:oauth_token] ? route_hidden.call(send(options[:oauth_token].to_sym)) : route_hidden.call
|
289
308
|
end
|
290
309
|
|
291
310
|
def public_parameter?(param)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
module GrapeSwagger
|
6
|
+
module Rake
|
7
|
+
class OapiTasks < ::Rake::TaskLib
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
attr_reader :oapi
|
11
|
+
attr_reader :api_class
|
12
|
+
|
13
|
+
def initialize(api_class)
|
14
|
+
super()
|
15
|
+
|
16
|
+
@api_class = api_class
|
17
|
+
define_tasks
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def define_tasks
|
23
|
+
namespace :oapi do
|
24
|
+
fetch
|
25
|
+
validate
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# tasks
|
30
|
+
#
|
31
|
+
# get swagger/OpenAPI documentation
|
32
|
+
def fetch
|
33
|
+
desc 'generates OpenApi documentation …
|
34
|
+
params (usage: key=value):
|
35
|
+
store – save as JSON file, default: false (optional)
|
36
|
+
resource - if given only for that it would be generated (optional)'
|
37
|
+
task fetch: :environment do
|
38
|
+
make_request
|
39
|
+
|
40
|
+
save_to_file? ? File.write(file, @oapi) : $stdout.print(@oapi)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# validates swagger/OpenAPI documentation
|
45
|
+
def validate
|
46
|
+
desc 'validates the generated OpenApi file …
|
47
|
+
params (usage: key=value):
|
48
|
+
resource - if given only for that it would be generated (optional)'
|
49
|
+
task validate: :environment do
|
50
|
+
ENV['store'] = 'true'
|
51
|
+
::Rake::Task['oapi:fetch'].invoke
|
52
|
+
exit if error?
|
53
|
+
|
54
|
+
output = system "swagger validate #{file}"
|
55
|
+
|
56
|
+
$stdout.puts 'install swagger-cli with `npm install swagger-cli -g`' if output.nil?
|
57
|
+
FileUtils.rm(file)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# helper methods
|
62
|
+
#
|
63
|
+
def make_request
|
64
|
+
get url_for
|
65
|
+
last_response
|
66
|
+
@oapi = JSON.pretty_generate(
|
67
|
+
JSON.parse(
|
68
|
+
last_response.body, symolize_names: true
|
69
|
+
)
|
70
|
+
) + "\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
def url_for
|
74
|
+
oapi_route = api_class.routes[-2]
|
75
|
+
path = oapi_route.path.sub(/\(\.\w+\)$/, '').sub(/\(\.:\w+\)$/, '')
|
76
|
+
path.sub!(':version', oapi_route.version.to_s)
|
77
|
+
|
78
|
+
[path, ENV['resource']].join('/').chomp('/')
|
79
|
+
end
|
80
|
+
|
81
|
+
def save_to_file?
|
82
|
+
ENV['store'].present? && !error?
|
83
|
+
end
|
84
|
+
|
85
|
+
def error?
|
86
|
+
JSON.parse(@oapi).keys.first == 'error'
|
87
|
+
end
|
88
|
+
|
89
|
+
def file
|
90
|
+
name = ENV['store'] == 'true' || ENV['store'].blank? ? 'swagger_doc.json' : ENV['store']
|
91
|
+
File.join(Dir.getwd, name)
|
92
|
+
end
|
93
|
+
|
94
|
+
def app
|
95
|
+
api_class.new
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'grape-entity'
|
3
|
+
require 'grape-swagger-entity'
|
4
|
+
|
5
|
+
describe 'definition names' do
|
6
|
+
before :all do
|
7
|
+
module TestDefinition
|
8
|
+
module DummyEntities
|
9
|
+
module WithVeryLongName
|
10
|
+
module AnotherGroupingModule
|
11
|
+
class Class1
|
12
|
+
class Entity < Grape::Entity
|
13
|
+
expose :one_thing
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Class2
|
18
|
+
class Entity < Grape::Entity
|
19
|
+
expose :another_thing
|
20
|
+
|
21
|
+
def self.entity_name
|
22
|
+
'FooKlass'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class NameApi < Grape::API
|
31
|
+
add_swagger_documentation models: [
|
32
|
+
DummyEntities::WithVeryLongName::AnotherGroupingModule::Class1::Entity,
|
33
|
+
DummyEntities::WithVeryLongName::AnotherGroupingModule::Class2::Entity
|
34
|
+
]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
let(:app) { TestDefinition::NameApi }
|
40
|
+
|
41
|
+
subject do
|
42
|
+
get '/swagger_doc'
|
43
|
+
JSON.parse(last_response.body)['definitions']
|
44
|
+
end
|
45
|
+
|
46
|
+
specify { expect(subject).to include 'AnotherGroupingModuleClass1' }
|
47
|
+
specify { expect(subject).to include 'FooKlass' }
|
48
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe GrapeSwagger::Rake::OapiTasks do
|
4
|
+
let(:api) do
|
5
|
+
item = Class.new(Grape::API) do
|
6
|
+
version 'v1', using: :path
|
7
|
+
|
8
|
+
resource :item do
|
9
|
+
get '/'
|
10
|
+
end
|
11
|
+
|
12
|
+
resource :otherItem do
|
13
|
+
get '/'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Class.new(Grape::API) do
|
18
|
+
prefix :api
|
19
|
+
mount item
|
20
|
+
add_swagger_documentation add_version: true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
subject { described_class.new(api) }
|
25
|
+
|
26
|
+
describe '#make_request' do
|
27
|
+
describe 'complete documentation' do
|
28
|
+
before do
|
29
|
+
subject.send(:make_request)
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'not storing' do
|
33
|
+
it 'has no error' do
|
34
|
+
expect(subject.send(:error?)).to be false
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does not allow to save' do
|
38
|
+
expect(subject.send(:save_to_file?)).to be false
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'requests doc url' do
|
42
|
+
expect(subject.send(:url_for)).to eql '/api/swagger_doc'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'store it' do
|
47
|
+
before { ENV['store'] = 'true' }
|
48
|
+
after { ENV.delete('store') }
|
49
|
+
|
50
|
+
it 'allows to save' do
|
51
|
+
expect(subject.send(:save_to_file?)).to be true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'documentation for resource' do
|
57
|
+
before do
|
58
|
+
ENV['resource'] = resource
|
59
|
+
subject.send(:make_request)
|
60
|
+
end
|
61
|
+
|
62
|
+
let(:response) { JSON.parse(subject.send(:make_request)) }
|
63
|
+
|
64
|
+
after { ENV.delete('resource') }
|
65
|
+
|
66
|
+
describe 'valid name' do
|
67
|
+
let(:resource) { 'otherItem' }
|
68
|
+
|
69
|
+
it 'has no error' do
|
70
|
+
expect(subject.send(:error?)).to be false
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'requests doc url' do
|
74
|
+
expect(subject.send(:url_for)).to eql "/api/swagger_doc/#{resource}"
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'has only one resource path' do
|
78
|
+
expect(response['paths'].length).to eql 1
|
79
|
+
expect(response['paths'].keys.first).to end_with resource
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'wrong name' do
|
84
|
+
let(:resource) { 'foo' }
|
85
|
+
|
86
|
+
it 'has error' do
|
87
|
+
expect(subject.send(:error?)).to be true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'empty name' do
|
92
|
+
let(:resource) { nil }
|
93
|
+
|
94
|
+
it 'has no error' do
|
95
|
+
expect(subject.send(:error?)).to be false
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'returns complete doc' do
|
99
|
+
expect(response['paths'].length).to eql 2
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#file' do
|
106
|
+
describe 'no store given' do
|
107
|
+
it 'returns swagger_doc.json' do
|
108
|
+
expect(subject.send(:file)).to end_with 'swagger_doc.json'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'store given' do
|
113
|
+
after { ENV.delete('store') }
|
114
|
+
|
115
|
+
describe 'boolean true' do
|
116
|
+
before { ENV['store'] = 'true' }
|
117
|
+
|
118
|
+
it 'returns swagger_doc.json' do
|
119
|
+
expect(subject.send(:file)).to end_with 'swagger_doc.json'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'name given' do
|
124
|
+
let(:name) { 'oapi_doc.json' }
|
125
|
+
before { ENV['store'] = name }
|
126
|
+
|
127
|
+
it 'returns swagger_doc.json' do
|
128
|
+
expect(subject.send(:file)).to end_with name
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -39,6 +39,8 @@ describe 'body parameter definitions' do
|
|
39
39
|
'body_param' => { 'type' => 'string', 'description' => 'param' },
|
40
40
|
'body_type_as_const_param' => { 'type' => 'string', 'description' => 'string_param' }
|
41
41
|
)
|
42
|
+
|
43
|
+
expect(subject['paths']['/endpoint']['post']['parameters'].any? { |p| p['name'] == 'XAuthToken' && p['in'] == 'header' }).to eql(true)
|
42
44
|
end
|
43
45
|
end
|
44
46
|
end
|
@@ -2,8 +2,6 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'details' do
|
4
4
|
describe 'details, pass markdown with redcarpet even with nil description and detail', unless: RUBY_PLATFORM.eql?('java') do
|
5
|
-
include_context 'the api entities'
|
6
|
-
|
7
5
|
before :all do
|
8
6
|
module TheApi
|
9
7
|
class GfmRcDetailApi < Grape::API
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
class SampleAuth < Grape::Middleware::Base
|
6
|
+
module AuthMethods
|
7
|
+
attr_accessor :access_token
|
8
|
+
|
9
|
+
def protected_endpoint=(protected)
|
10
|
+
@protected_endpoint = protected
|
11
|
+
end
|
12
|
+
|
13
|
+
def protected_endpoint?
|
14
|
+
@protected_endpoint || false
|
15
|
+
end
|
16
|
+
|
17
|
+
def access_token
|
18
|
+
@_access_token
|
19
|
+
end
|
20
|
+
|
21
|
+
def access_token=(token)
|
22
|
+
@_access_token = token
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def context
|
27
|
+
env['api.endpoint']
|
28
|
+
end
|
29
|
+
|
30
|
+
def before
|
31
|
+
context.extend(SampleAuth::AuthMethods)
|
32
|
+
context.protected_endpoint = context.options[:route_options][:auth].present?
|
33
|
+
|
34
|
+
return unless context.protected_endpoint?
|
35
|
+
scopes = context.options[:route_options][:auth][:scopes].map(&:to_sym)
|
36
|
+
authorize!(*scopes) unless scopes.include? :false
|
37
|
+
context.access_token = env['HTTP_AUTHORIZATION']
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module Extension
|
42
|
+
def sample_auth(*scopes)
|
43
|
+
description = route_setting(:description) || route_setting(:description, {})
|
44
|
+
description[:auth] = { scopes: scopes }
|
45
|
+
end
|
46
|
+
|
47
|
+
Grape::API.extend self
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'a guarded api endpoint' do
|
51
|
+
before :all do
|
52
|
+
class GuardedMountedApi < Grape::API
|
53
|
+
access_token_valid = proc { |token = nil| token.nil? || token != '12345' }
|
54
|
+
|
55
|
+
desc 'Show endpoint if authenticated', hidden: access_token_valid
|
56
|
+
get '/auth' do
|
57
|
+
{ foo: 'bar' }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class GuardedApi < Grape::API
|
62
|
+
mount GuardedMountedApi
|
63
|
+
add_swagger_documentation endpoint_auth_wrapper: SampleAuth,
|
64
|
+
swagger_endpoint_guard: 'sample_auth false',
|
65
|
+
oauth_token: 'access_token'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def app
|
70
|
+
GuardedApi
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when a correct token is passed with the request' do
|
74
|
+
subject do
|
75
|
+
get '/swagger_doc.json', {}, 'HTTP_AUTHORIZATION' => '12345'
|
76
|
+
JSON.parse(last_response.body)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'retrieves swagger-documentation for the endpoint' do
|
80
|
+
expect(subject).to eq(
|
81
|
+
'info' => { 'title' => 'API title', 'version' => '0.0.1' },
|
82
|
+
'swagger' => '2.0',
|
83
|
+
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
|
84
|
+
'host' => 'example.org',
|
85
|
+
'paths' => {
|
86
|
+
'/auth' => {
|
87
|
+
'get' => {
|
88
|
+
'summary' => 'Show endpoint if authenticated',
|
89
|
+
'description' => 'Show endpoint if authenticated',
|
90
|
+
'produces' => ['application/json'],
|
91
|
+
'tags' => ['auth'],
|
92
|
+
'operationId' => 'getAuth',
|
93
|
+
'responses' => { '200' => { 'description' => 'Show endpoint if authenticated' } }
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'when a bad token is passed with the request' do
|
102
|
+
subject do
|
103
|
+
get '/swagger_doc.json', {}, 'HTTP_AUTHORIZATION' => '123456'
|
104
|
+
JSON.parse(last_response.body)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'does not retrieve swagger-documentation for the endpoint - only the info_object' do
|
108
|
+
expect(subject).to eq(
|
109
|
+
'info' => { 'title' => 'API title', 'version' => '0.0.1' },
|
110
|
+
'swagger' => '2.0',
|
111
|
+
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
|
112
|
+
'host' => 'example.org'
|
113
|
+
)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/spec/swagger_v2/host.rb
CHANGED
@@ -64,4 +64,56 @@ describe 'namespace' do
|
|
64
64
|
expect(subject['description']).to eql('Description for aspace')
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
68
|
+
context 'mounted under a route' do
|
69
|
+
def app
|
70
|
+
namespaced_api = Class.new(Grape::API) do
|
71
|
+
namespace :bspace do
|
72
|
+
get '/', desc: 'Description for aspace'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
Class.new(Grape::API) do
|
77
|
+
mount namespaced_api => '/mounted'
|
78
|
+
add_swagger_documentation format: :json
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
subject do
|
83
|
+
get '/swagger_doc'
|
84
|
+
JSON.parse(last_response.body)['paths']['/mounted/bspace']['get']
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'shows the namespace description in the json spec' do
|
88
|
+
expect(subject['description']).to eql('Description for aspace')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'arbitrary mounting' do
|
93
|
+
def app
|
94
|
+
inner_namespaced_api = Class.new(Grape::API) do
|
95
|
+
namespace :bspace do
|
96
|
+
get '/', desc: 'Description for aspace'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
outer_namespaced_api = Class.new(Grape::API) do
|
101
|
+
mount inner_namespaced_api => '/mounted'
|
102
|
+
end
|
103
|
+
|
104
|
+
Class.new(Grape::API) do
|
105
|
+
mount outer_namespaced_api => '/'
|
106
|
+
add_swagger_documentation format: :json
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
subject do
|
111
|
+
get '/swagger_doc'
|
112
|
+
JSON.parse(last_response.body)['paths']['/mounted/bspace']['get']
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'shows the namespace description in the json spec' do
|
116
|
+
expect(subject['description']).to eql('Description for aspace')
|
117
|
+
end
|
118
|
+
end
|
67
119
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Group Array Params, using collection format' do
|
4
|
+
def app
|
5
|
+
Class.new(Grape::API) do
|
6
|
+
format :json
|
7
|
+
|
8
|
+
params do
|
9
|
+
optional :array_of_strings, type: Array[String], desc: 'array in csv collection format'
|
10
|
+
end
|
11
|
+
|
12
|
+
get '/array_of_strings_without_collection_format' do
|
13
|
+
{ 'declared_params' => declared(params) }
|
14
|
+
end
|
15
|
+
|
16
|
+
params do
|
17
|
+
optional :array_of_strings, type: Array[String], desc: 'array in multi collection format', documentation: { collectionFormat: 'multi' }
|
18
|
+
end
|
19
|
+
|
20
|
+
get '/array_of_strings_multi_collection_format' do
|
21
|
+
{ 'declared_params' => declared(params) }
|
22
|
+
end
|
23
|
+
|
24
|
+
params do
|
25
|
+
optional :array_of_strings, type: Array[String], documentation: { collectionFormat: 'foo' }
|
26
|
+
end
|
27
|
+
|
28
|
+
get '/array_of_strings_invalid_collection_format' do
|
29
|
+
{ 'declared_params' => declared(params) }
|
30
|
+
end
|
31
|
+
|
32
|
+
add_swagger_documentation
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'documentation for array parameter in default csv collectionFormat' do
|
37
|
+
subject do
|
38
|
+
get '/swagger_doc/array_of_strings_without_collection_format'
|
39
|
+
JSON.parse(last_response.body)
|
40
|
+
end
|
41
|
+
|
42
|
+
specify do
|
43
|
+
expect(subject['paths']['/array_of_strings_without_collection_format']['get']['parameters']).to eql(
|
44
|
+
[
|
45
|
+
{ 'in' => 'formData', 'name' => 'array_of_strings', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => false, 'description' => 'array in csv collection format' }
|
46
|
+
]
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'documentation for array parameters in multi collectionFormat set from documentation' do
|
52
|
+
subject do
|
53
|
+
get '/swagger_doc/array_of_strings_multi_collection_format'
|
54
|
+
JSON.parse(last_response.body)
|
55
|
+
end
|
56
|
+
|
57
|
+
specify do
|
58
|
+
expect(subject['paths']['/array_of_strings_multi_collection_format']['get']['parameters']).to eql(
|
59
|
+
[
|
60
|
+
{ 'in' => 'formData', 'name' => 'array_of_strings', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => false, 'collectionFormat' => 'multi', 'description' => 'array in multi collection format' }
|
61
|
+
]
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'documentation for array parameters with collectionFormat set to invalid option' do
|
67
|
+
subject do
|
68
|
+
get '/swagger_doc/array_of_strings_invalid_collection_format'
|
69
|
+
JSON.parse(last_response.body)
|
70
|
+
end
|
71
|
+
|
72
|
+
specify do
|
73
|
+
expect(subject['paths']['/array_of_strings_invalid_collection_format']['get']['parameters']).to eql(
|
74
|
+
[
|
75
|
+
{ 'in' => 'formData', 'name' => 'array_of_strings', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => false }
|
76
|
+
]
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'security requirement on endpoint method' do
|
4
|
+
def app
|
5
|
+
Class.new(Grape::API) do
|
6
|
+
desc 'Endpoint with security requirement', security: [oauth_pets: ['read:pets', 'write:pets']]
|
7
|
+
get '/with_security' do
|
8
|
+
{ foo: 'bar' }
|
9
|
+
end
|
10
|
+
|
11
|
+
add_swagger_documentation
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
subject do
|
16
|
+
get '/swagger_doc.json'
|
17
|
+
JSON.parse(last_response.body)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'defines the security requirement on the endpoint method' do
|
21
|
+
expect(subject['paths']['/with_security']['get']['security']).to eql ['oauth_pets' => ['read:pets', 'write:pets']]
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grape-swagger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.24.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Vandecasteele
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grape
|
@@ -255,13 +255,16 @@ files:
|
|
255
255
|
- lib/grape-swagger/markdown/kramdown_adapter.rb
|
256
256
|
- lib/grape-swagger/markdown/redcarpet_adapter.rb
|
257
257
|
- lib/grape-swagger/model_parsers.rb
|
258
|
+
- lib/grape-swagger/rake/oapi_tasks.rb
|
258
259
|
- lib/grape-swagger/version.rb
|
259
260
|
- spec/issues/403_versions_spec.rb
|
261
|
+
- spec/issues/430_entity_definitions_spec.rb
|
260
262
|
- spec/lib/data_type_spec.rb
|
261
263
|
- spec/lib/endpoint_spec.rb
|
262
264
|
- spec/lib/extensions_spec.rb
|
263
265
|
- spec/lib/model_parsers_spec.rb
|
264
266
|
- spec/lib/move_params_spec.rb
|
267
|
+
- spec/lib/oapi_tasks_spec.rb
|
265
268
|
- spec/lib/operation_id_spec.rb
|
266
269
|
- spec/lib/optional_object_spec.rb
|
267
270
|
- spec/lib/path_string_spec.rb
|
@@ -304,6 +307,7 @@ files:
|
|
304
307
|
- spec/swagger_v2/float_api_spec.rb
|
305
308
|
- spec/swagger_v2/form_params_spec.rb
|
306
309
|
- spec/swagger_v2/grape-swagger_spec.rb
|
310
|
+
- spec/swagger_v2/guarded_endpoint_spec.rb
|
307
311
|
- spec/swagger_v2/hide_api_spec.rb
|
308
312
|
- spec/swagger_v2/host.rb
|
309
313
|
- spec/swagger_v2/mounted_target_class_spec.rb
|
@@ -314,10 +318,12 @@ files:
|
|
314
318
|
- spec/swagger_v2/param_multi_type_spec.rb
|
315
319
|
- spec/swagger_v2/param_type_spec.rb
|
316
320
|
- spec/swagger_v2/param_values_spec.rb
|
321
|
+
- spec/swagger_v2/params_array_collection_fromat_spec.rb
|
317
322
|
- spec/swagger_v2/params_array_spec.rb
|
318
323
|
- spec/swagger_v2/params_hash_spec.rb
|
319
324
|
- spec/swagger_v2/params_nested_spec.rb
|
320
325
|
- spec/swagger_v2/reference_entity.rb
|
326
|
+
- spec/swagger_v2/security_requirement_spec.rb
|
321
327
|
- spec/swagger_v2/simple_mounted_api_spec.rb
|
322
328
|
- spec/version_spec.rb
|
323
329
|
homepage: https://github.com/ruby-grape/grape-swagger
|
@@ -340,18 +346,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
340
346
|
version: '0'
|
341
347
|
requirements: []
|
342
348
|
rubyforge_project:
|
343
|
-
rubygems_version: 2.6.
|
349
|
+
rubygems_version: 2.6.6
|
344
350
|
signing_key:
|
345
351
|
specification_version: 4
|
346
352
|
summary: A simple way to add auto generated documentation to your Grape API that can
|
347
353
|
be displayed with Swagger.
|
348
354
|
test_files:
|
349
355
|
- spec/issues/403_versions_spec.rb
|
356
|
+
- spec/issues/430_entity_definitions_spec.rb
|
350
357
|
- spec/lib/data_type_spec.rb
|
351
358
|
- spec/lib/endpoint_spec.rb
|
352
359
|
- spec/lib/extensions_spec.rb
|
353
360
|
- spec/lib/model_parsers_spec.rb
|
354
361
|
- spec/lib/move_params_spec.rb
|
362
|
+
- spec/lib/oapi_tasks_spec.rb
|
355
363
|
- spec/lib/operation_id_spec.rb
|
356
364
|
- spec/lib/optional_object_spec.rb
|
357
365
|
- spec/lib/path_string_spec.rb
|
@@ -394,6 +402,7 @@ test_files:
|
|
394
402
|
- spec/swagger_v2/float_api_spec.rb
|
395
403
|
- spec/swagger_v2/form_params_spec.rb
|
396
404
|
- spec/swagger_v2/grape-swagger_spec.rb
|
405
|
+
- spec/swagger_v2/guarded_endpoint_spec.rb
|
397
406
|
- spec/swagger_v2/hide_api_spec.rb
|
398
407
|
- spec/swagger_v2/host.rb
|
399
408
|
- spec/swagger_v2/mounted_target_class_spec.rb
|
@@ -404,9 +413,11 @@ test_files:
|
|
404
413
|
- spec/swagger_v2/param_multi_type_spec.rb
|
405
414
|
- spec/swagger_v2/param_type_spec.rb
|
406
415
|
- spec/swagger_v2/param_values_spec.rb
|
416
|
+
- spec/swagger_v2/params_array_collection_fromat_spec.rb
|
407
417
|
- spec/swagger_v2/params_array_spec.rb
|
408
418
|
- spec/swagger_v2/params_hash_spec.rb
|
409
419
|
- spec/swagger_v2/params_nested_spec.rb
|
410
420
|
- spec/swagger_v2/reference_entity.rb
|
421
|
+
- spec/swagger_v2/security_requirement_spec.rb
|
411
422
|
- spec/swagger_v2/simple_mounted_api_spec.rb
|
412
423
|
- spec/version_spec.rb
|