apicasso 0.5.1 → 0.5.2
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/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