apicasso 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/apicasso/apidocs_controller.rb +209 -206
- data/app/controllers/concerns/sql_security.rb +1 -1
- data/lib/apicasso/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c1f920e9964f2f638e348b6acb79ee6fd0f922a06d0cc43282696be53325ba9
|
4
|
+
data.tar.gz: 83e3b5a19723736f4c72e0263159aea8a73ccc5b620ad63c6b0dc2f3adea4734
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2465d5459eae0c3203903659f9e7a01b55086caffc57c245058518c8510e3689cc3a67b1d1f954125b2915121661f01ca171aa45292875a4ac74053ddbb9543b
|
7
|
+
data.tar.gz: 227061cbc6efc8976acc17bd2d34dd5989aeaab549535c30ccb83835b6e87ff8a76ca1d7a7f17357df9e7d621db51b0f4c22ca3453d370066e842cab18d7f3f2
|
@@ -7,7 +7,6 @@ module Apicasso
|
|
7
7
|
skip_before_action :restrict_access
|
8
8
|
|
9
9
|
include Swagger::Blocks
|
10
|
-
|
11
10
|
# Default application settings for documentation generation.
|
12
11
|
# Define here the title of the application, logo, description, terms
|
13
12
|
# of service, contact of the developer and the license of the application.
|
@@ -26,7 +25,8 @@ module Apicasso
|
|
26
25
|
info do
|
27
26
|
key :title, ENV.fetch('APP_NAME', I18n.t('application.name'))
|
28
27
|
# The x-logo key is responsible for the logo in the documentation
|
29
|
-
key 'x-logo',
|
28
|
+
key 'x-logo', url: I18n.t('app.logo.url', default: 'https://raw.githubusercontent.com/ErvalhouS/APIcasso/master/APIcasso.png'),
|
29
|
+
altText: I18n.t('app.logo.alttext', default: 'Application Logo')
|
30
30
|
key :description, ENV.fetch('APP_DESCRIPTION', I18n.t('application.description'))
|
31
31
|
key :termsOfService, I18n.t('application.terms_of_service')
|
32
32
|
contact do
|
@@ -125,237 +125,239 @@ module Apicasso
|
|
125
125
|
end
|
126
126
|
|
127
127
|
# Builds JSON of definitions with operations from each model
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
key :
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
key :collectionFormat, :json
|
145
|
-
end
|
146
|
-
parameter do
|
147
|
-
key :name, :q
|
148
|
-
key :in, :query
|
149
|
-
key :description, I18n.t('apicasso.q.description',
|
150
|
-
default: 'Records filtering by attribute and search query as affix. Usage: `?q[{attribute}{search_affix}]={matcher}`. All available search affixes are listed on: https://github.com/activerecord-hackery/ransack#search-matchers')
|
151
|
-
key :required, false
|
152
|
-
key :type, :json
|
153
|
-
end
|
154
|
-
parameter do
|
155
|
-
key :name, :page
|
156
|
-
key :in, :query
|
157
|
-
key :description, I18n.t('apicasso.page.description',
|
158
|
-
default: 'Records pagination paging, which offsets collection based on `params[:per_page]`')
|
159
|
-
key :required, false
|
160
|
-
key :type, :integer
|
161
|
-
end
|
162
|
-
parameter do
|
163
|
-
key :name, :per_page
|
164
|
-
key :in, :query
|
165
|
-
key :description, I18n.t('apicasso.per_page.description',
|
166
|
-
default: 'Records pagination size, which sets how many records will be rendered per request')
|
167
|
-
key :required, false
|
168
|
-
key :type, :integer
|
169
|
-
end
|
170
|
-
response 200 do
|
171
|
-
key :description, I18n.t("activerecord.models.#{model.name.underscore}.index.response",
|
172
|
-
default: "#{model.name} response, which include records matching current query and pagination metadata")
|
173
|
-
schema do
|
174
|
-
key :name, :total
|
175
|
-
key :description, I18n.t('apicasso.total.description',
|
176
|
-
default: 'Total records contained in current collection, as if there was no pagination.')
|
177
|
-
key :required, true
|
178
|
-
key :type, :integer
|
179
|
-
end
|
180
|
-
schema do
|
181
|
-
key :name, :total_pages
|
182
|
-
key :description, I18n.t('apicasso.total_pages.description',
|
183
|
-
default: 'How many pages of data the current collection has.')
|
184
|
-
key :required, true
|
185
|
-
key :type, :integer
|
186
|
-
end
|
187
|
-
schema do
|
188
|
-
key :name, :last_page
|
189
|
-
key :description, I18n.t('apicasso.last_page.description',
|
190
|
-
default: 'An indication if current request is the last to paginate in the current collection')
|
191
|
-
key :required, true
|
192
|
-
key :type, :boolean
|
193
|
-
end
|
194
|
-
schema do
|
195
|
-
key :name, :previous_page
|
196
|
-
key :description, I18n.t('apicasso.previous_page.description',
|
197
|
-
default: "The link of the previous page for the current collection. It can be null if there isn't any")
|
128
|
+
ActiveRecord::Base.descendants.each do |model|
|
129
|
+
next if MODELS_EXCLUDED.include?(model.name) || model.abstract_class
|
130
|
+
|
131
|
+
# Resource definitions of GET, OPTIONS, POST
|
132
|
+
swagger_path "/#{model.name.underscore}" do
|
133
|
+
operation :get do
|
134
|
+
key :summary, I18n.t("activerecord.models.#{model.name.underscore}.index.summary", default: model.name)
|
135
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.index.description", default: model.name)
|
136
|
+
key :operationId, "find#{model.name.pluralize}"
|
137
|
+
key :produces, ['application/json']
|
138
|
+
key :tags, [model.name.underscore]
|
139
|
+
parameter do
|
140
|
+
key :name, :sort
|
141
|
+
key :in, :query
|
142
|
+
key :description, I18n.t('apicasso.sort.description',
|
143
|
+
default: 'Parameters sorting splitted by `,` preffixed by `+` or `-` which translates into ascending or descending order')
|
198
144
|
key :required, false
|
199
145
|
key :type, :string
|
146
|
+
key :collectionFormat, :json
|
200
147
|
end
|
201
|
-
|
202
|
-
key :name, :
|
203
|
-
key :
|
204
|
-
|
148
|
+
parameter do
|
149
|
+
key :name, :q
|
150
|
+
key :in, :query
|
151
|
+
key :description, I18n.t('apicasso.q.description',
|
152
|
+
default: 'Records filtering by attribute and search query as affix. Usage: `?q[{attribute}{search_affix}]={matcher}`. All available search affixes are listed on: https://github.com/activerecord-hackery/ransack#search-matchers')
|
205
153
|
key :required, false
|
206
|
-
key :type, :
|
154
|
+
key :type, :json
|
207
155
|
end
|
208
|
-
|
209
|
-
key :name, :
|
210
|
-
key :
|
211
|
-
|
212
|
-
|
213
|
-
key :
|
156
|
+
parameter do
|
157
|
+
key :name, :page
|
158
|
+
key :in, :query
|
159
|
+
key :description, I18n.t('apicasso.page.description',
|
160
|
+
default: 'Records pagination paging, which offsets collection based on `params[:per_page]`')
|
161
|
+
key :required, false
|
162
|
+
key :type, :integer
|
214
163
|
end
|
215
|
-
|
216
|
-
key :name, :
|
217
|
-
key :
|
218
|
-
|
219
|
-
|
164
|
+
parameter do
|
165
|
+
key :name, :per_page
|
166
|
+
key :in, :query
|
167
|
+
key :description, I18n.t('apicasso.per_page.description',
|
168
|
+
default: 'Records pagination size, which sets how many records will be rendered per request')
|
169
|
+
key :required, false
|
220
170
|
key :type, :integer
|
221
171
|
end
|
222
|
-
|
223
|
-
key :name,
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
key :
|
172
|
+
response 200 do
|
173
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.index.response",
|
174
|
+
default: "#{model.name} response, which include records matching current query and pagination metadata")
|
175
|
+
schema do
|
176
|
+
key :name, :total
|
177
|
+
key :description, I18n.t('apicasso.total.description',
|
178
|
+
default: 'Total records contained in current collection, as if there was no pagination.')
|
179
|
+
key :required, true
|
180
|
+
key :type, :integer
|
181
|
+
end
|
182
|
+
schema do
|
183
|
+
key :name, :total_pages
|
184
|
+
key :description, I18n.t('apicasso.total_pages.description',
|
185
|
+
default: 'How many pages of data the current collection has.')
|
186
|
+
key :required, true
|
187
|
+
key :type, :integer
|
188
|
+
end
|
189
|
+
schema do
|
190
|
+
key :name, :last_page
|
191
|
+
key :description, I18n.t('apicasso.last_page.description',
|
192
|
+
default: 'An indication if current request is the last to paginate in the current collection')
|
193
|
+
key :required, true
|
194
|
+
key :type, :boolean
|
195
|
+
end
|
196
|
+
schema do
|
197
|
+
key :name, :previous_page
|
198
|
+
key :description, I18n.t('apicasso.previous_page.description',
|
199
|
+
default: "The link of the previous page for the current collection. It can be null if there isn't any")
|
200
|
+
key :required, false
|
201
|
+
key :type, :string
|
202
|
+
end
|
203
|
+
schema do
|
204
|
+
key :name, :next_page
|
205
|
+
key :description, I18n.t('apicasso.next_page.description',
|
206
|
+
default: "The link of the next page for the current collection. It can be null if there isn't any")
|
207
|
+
key :required, false
|
208
|
+
key :type, :string
|
209
|
+
end
|
210
|
+
schema do
|
211
|
+
key :name, :out_of_bounds
|
212
|
+
key :description, I18n.t('apicasso.out_of_bounds.description',
|
213
|
+
default: 'An indication if current request is out of pagination bounds for the current collection')
|
214
|
+
key :required, true
|
215
|
+
key :type, :boolean
|
216
|
+
end
|
217
|
+
schema do
|
218
|
+
key :name, :offset
|
219
|
+
key :description, I18n.t('apicasso.offset.description',
|
220
|
+
default: 'How many records were offsetted from the collection to render the current page')
|
221
|
+
key :required, true
|
222
|
+
key :type, :integer
|
223
|
+
end
|
224
|
+
schema do
|
225
|
+
key :name, :entries
|
226
|
+
key :description, I18n.t('apicasso.entries.description',
|
227
|
+
default: 'The records collection in the current pagination scope.')
|
228
|
+
key :required, true
|
229
|
+
key :type, :array
|
230
|
+
items do
|
231
|
+
key :'$ref', model.name.to_sym
|
232
|
+
end
|
230
233
|
end
|
231
234
|
end
|
232
235
|
end
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
236
|
+
operation :options do
|
237
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.schema.description",
|
238
|
+
default: "#{model.name} metadata information.")
|
239
|
+
key :operationId, "schema#{model.name.pluralize}"
|
240
|
+
key :produces, ['application/json']
|
241
|
+
key :tags, [model.name.underscore]
|
242
|
+
response 200 do
|
243
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.schema.response",
|
244
|
+
default: "#{model.name} metadata as a json with field names as keys and field types as values.")
|
245
|
+
schema do
|
246
|
+
key :'$ref', "#{model.name}".to_sym
|
247
|
+
end
|
245
248
|
end
|
246
249
|
end
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
250
|
+
operation :post do
|
251
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.create.response",
|
252
|
+
default: "Creates a #{model.name}")
|
253
|
+
key :operationId, "add#{model.name}"
|
254
|
+
key :produces, ['application/json']
|
255
|
+
key :tags, [model.name.underscore]
|
256
|
+
parameter do
|
257
|
+
key :name, model.name.underscore.to_sym
|
258
|
+
key :in, :body
|
259
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.create.description",
|
260
|
+
default: "#{model.name} to add into application")
|
261
|
+
key :required, true
|
262
|
+
schema do
|
263
|
+
key :'$ref', "#{model.name}".to_sym
|
264
|
+
end
|
262
265
|
end
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
266
|
+
response 201 do
|
267
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
|
268
|
+
default: "#{model.name} response")
|
269
|
+
schema do
|
270
|
+
key :'$ref', model.name.to_sym
|
271
|
+
end
|
269
272
|
end
|
270
273
|
end
|
271
274
|
end
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
key :'$ref', "#{model.name}".to_sym
|
275
|
+
swagger_path "/#{model.name.underscore}/{id}" do
|
276
|
+
operation :patch do
|
277
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.update.response",
|
278
|
+
default: "Updates a #{model.name}")
|
279
|
+
key :operationId, "edit#{model.name}"
|
280
|
+
key :produces, ['application/json']
|
281
|
+
key :tags, [model.name.underscore]
|
282
|
+
parameter do
|
283
|
+
key :name, :id
|
284
|
+
key :in, :path
|
285
|
+
key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
|
286
|
+
default: "ID of #{model.name} to update on the application")
|
287
|
+
key :required, true
|
288
|
+
schema do
|
289
|
+
key :'$ref', "#{model.name}".to_sym
|
290
|
+
end
|
289
291
|
end
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
292
|
+
parameter do
|
293
|
+
key :name, model.name.underscore.to_sym
|
294
|
+
key :in, :body
|
295
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.update.description",
|
296
|
+
default: "Existing #{model.name} to update on the application")
|
297
|
+
key :required, true
|
298
|
+
schema do
|
299
|
+
key :'$ref', "#{model.name}".to_sym
|
300
|
+
end
|
299
301
|
end
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
302
|
+
response 200 do
|
303
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
|
304
|
+
default: "#{model.name} response")
|
305
|
+
schema do
|
306
|
+
key :'$ref', model.name.to_sym
|
307
|
+
end
|
306
308
|
end
|
307
309
|
end
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
310
|
+
operation :get do
|
311
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.response",
|
312
|
+
default: "Creates a #{model.name}")
|
313
|
+
key :operationId, "show#{model.name}"
|
314
|
+
key :produces, ['application/json']
|
315
|
+
key :tags, [model.name.underscore]
|
316
|
+
parameter do
|
317
|
+
key :name, :id
|
318
|
+
key :in, :path
|
319
|
+
key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
|
320
|
+
default: "ID of #{model.name} to fetch on the application")
|
321
|
+
key :required, true
|
322
|
+
schema do
|
323
|
+
key :'$ref', "#{model.name}".to_sym
|
324
|
+
end
|
323
325
|
end
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
326
|
+
response 200 do
|
327
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
|
328
|
+
default: "#{model.name} response")
|
329
|
+
schema do
|
330
|
+
key :'$ref', model.name.to_sym
|
331
|
+
end
|
330
332
|
end
|
331
333
|
end
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
334
|
+
operation :delete do
|
335
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.destroy.response",
|
336
|
+
default: "Deletes a #{model.name}")
|
337
|
+
key :operationId, "destroy#{model.name}"
|
338
|
+
key :produces, ['application/json']
|
339
|
+
key :tags, [model.name.underscore]
|
340
|
+
parameter do
|
341
|
+
key :name, :id
|
342
|
+
key :in, :path
|
343
|
+
key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
|
344
|
+
default: "ID of #{model.name} to delete on the application")
|
345
|
+
key :required, true
|
346
|
+
schema do
|
347
|
+
key :'$ref', "#{model.name}".to_sym
|
348
|
+
end
|
349
|
+
end
|
350
|
+
response 200 do
|
351
|
+
key :description, I18n.t("activerecord.models.#{model.name.underscore}.destroy.description",
|
352
|
+
default: "#{model.name} response")
|
347
353
|
end
|
348
|
-
end
|
349
|
-
response 200 do
|
350
|
-
key :description, I18n.t("activerecord.models.#{model.name.underscore}.destroy.description",
|
351
|
-
default: "#{model.name} response")
|
352
354
|
end
|
353
355
|
end
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
356
|
+
|
357
|
+
# Resource's associations definitions
|
358
|
+
model.reflect_on_all_associations.map(&:name).each do |association|
|
359
|
+
inner_name = association.to_s.classify
|
360
|
+
next if ASSOCIATION_EXCLUDED.include?(inner_name)
|
359
361
|
inner_klass = begin inner_name.constantize rescue NameError; false end
|
360
362
|
swagger_path "/#{model.name.underscore}/{id}/#{association}" do
|
361
363
|
operation :get do
|
@@ -492,6 +494,7 @@ module Apicasso
|
|
492
494
|
end
|
493
495
|
end
|
494
496
|
end
|
497
|
+
|
495
498
|
# Method that serves the generated Swagger JSON
|
496
499
|
def index
|
497
500
|
render json: Swagger::Blocks.build_root_json(SWAGGERED_CLASSES).to_json
|
@@ -56,7 +56,7 @@ module SqlSecurity
|
|
56
56
|
# Check if value for current class is valid for API consumption
|
57
57
|
def safe_for_sql?(klass, value)
|
58
58
|
klass.column_names.include?(value) ||
|
59
|
-
DESCENDANTS_UNDERSCORED.include?(value
|
59
|
+
DESCENDANTS_UNDERSCORED.include?(value) ||
|
60
60
|
klass.new.respond_to?(value) ||
|
61
61
|
klass.reflect_on_all_associations.map(&:name).include?(value)
|
62
62
|
end
|
data/lib/apicasso/version.rb
CHANGED