rest_rails 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b126ebf0d0ee509d040b57b6ff35dd7bb3ab837c09e499159f369a8d56df21ee
4
- data.tar.gz: 91cbf7f438cfa373ba2c9d61f2d1f44f8e3eda84da4244dae1da01e384d898e7
3
+ metadata.gz: 652e20dd610f1f6647f5d4dadac3d16a6d782bc0dc9765993d8bd064eb571e4e
4
+ data.tar.gz: 4fcfb8bef731b3e1067f033d1d62eee2f31478e7f737673cc1100d222f491a69
5
5
  SHA512:
6
- metadata.gz: e6ca726a3603a6ed9ce3ceec63379e266a64c993677c063c9c693940e95d08105b311a9becfdc4380f12ad411e29088f1d7b58462afa0bc3810be8b29ae99483
7
- data.tar.gz: dc96c4175867bfc18c1fe059421e0613ee3ab0145ba7910953e62fe5d0ce8595096928ee869d448473ee70487f76679564298c45248b0d0ca1697bf9df09aa9c
6
+ metadata.gz: 8427c35cfdf814c694802321f3d4b8f808f38ba8cd1b92957cc70102d1c4b56331237688213d2348fbed2c712667162091b28a558e17fee28f103b02efeeb6e9
7
+ data.tar.gz: 2740b7604869ed36bf0fc594e385412b33c5bb4e3b4517cd69daba52f6fb40dc4fa63acc27409dd2b4f5fa30034978abb774fdaa922087aa01f8aa4c85112dfb
data/README.md CHANGED
@@ -3,10 +3,33 @@ Rails Plugin for quick intelligent API Creation by Tuitu Technology Solutions
3
3
 
4
4
  ## How To Start
5
5
 
6
+ ### Step 1: Basic Setup
6
7
  1. Add To Gemfile: `gem 'rest_rails'`
7
8
  2. Bundle Install: `bundle install`
8
9
  3. Install RestRails: `rails g rest_rails:install`
9
- 4. Modify initializer and/or mounted route.
10
+
11
+ ### Step 2: Change Mounted Path (optional)
12
+ 1. Make sure the line `mount RestRails::Engine => '/api/v1', as: 'rest'` is at the *bottom* of your routes. (This will prevent RestRails from taking over any custom API routing you might do)
13
+ 2. Change '/api/v1' to whatever naming structure you would like to prepend REST API routes.
14
+
15
+ ### Step 3: Whitelist Permitted Columns (optional)
16
+ 1. For better security, it is strongly recommended to setup the initializer to whitelist your columns.
17
+
18
+ Here is an example on how to whitelist columns for a sample database w/ three tables: articles, comments, users.
19
+ In this example, we only want the API to allow REST API endpoints for articles and comments, but not users.
20
+
21
+ *Note: table_names are keys. Acceptable values include: (:all, :none, or an Array of column_names)*
22
+
23
+ ```
24
+ RestRails.configure do |config|
25
+ # ...
26
+ config.permit = {
27
+ articles: :all,
28
+ users: :none,
29
+ comments: [:content]
30
+ }
31
+ end
32
+ ```
10
33
 
11
34
  ## The Basics
12
35
 
@@ -52,9 +75,9 @@ destroy | DELETE | `/api/v1/comments/:id` | destroy a
52
75
  fetch_column | GET | `/api/v1/comments/:id/article_id` | fetch article_id of comment
53
76
  fetch_column | GET | `/api/v1/comments/:id/content` | fetch content of comment
54
77
 
55
- # HOW TO USE THE REST API
78
+ # Using the REST API
56
79
 
57
- ## INDEX: GET '/table_name'
80
+ ## Index
58
81
  GET '/articles' will return a JSON response as follows:
59
82
  ```
60
83
  {
@@ -110,7 +133,7 @@ article\[description\]\[\] | *Array* | article\[description\]\[\]=SomeDescript
110
133
  article[content] | *String* | article[content]=Some+Content | Will match articles with contents same as the value.
111
134
  article\[content\]\[\] | *Array* | article\[content\]\[\]=SomeContent&article\[content\]\[\]=SomeOtherContent | Will match articles with content of 'SomeContent' OR 'SomeOtherContent'
112
135
 
113
- ## SHOW: GET '/table_name/:id'
136
+ ## Show
114
137
  GET '/articles/1' will return a JSON response as follows:
115
138
  ```
116
139
  {
@@ -139,7 +162,7 @@ GET '/articles/1' will return a JSON response as follows:
139
162
  }
140
163
  ```
141
164
 
142
- ## CREATE: POST '/table_name'
165
+ ## Create
143
166
 
144
167
  The create paths enforce Rails **strong params**. So only properly structured requests will be allowed.
145
168
  POST '/articles' can accept a payload in the following structure:
@@ -185,7 +208,7 @@ If successful (and passes your ActiveRecord validations), the response will be a
185
208
  }
186
209
  ```
187
210
 
188
- ## UPDATE: PATCH '/table_name/:id'
211
+ ## Update
189
212
 
190
213
  The update paths enforce Rails **strong params**. So only properly structured requests will be allowed.
191
214
  PATCH '/articles/1' can accept a payload in the following structure (with one or more columns to be updated):
@@ -230,7 +253,7 @@ If successful (and passes your ActiveRecord validations), the response will be a
230
253
  }
231
254
  ```
232
255
 
233
- ## DESTROY: DELETE '/table_name'
256
+ ## Destroy
234
257
 
235
258
  DELETE '/articles/1' only needs the ID number.
236
259
 
@@ -245,7 +268,7 @@ If successful (and passes your ActiveRecord validations), the response will be a
245
268
 
246
269
  **Note:** If you are using activestorage, the destroy process will also automatically destroy attachments from your bucket.
247
270
 
248
- ## FETCH_COLUMN: GET '/table_name/:id/:column_name'
271
+ ## Fetch Column
249
272
 
250
273
  GET '/articles/1/title'
251
274
 
@@ -290,19 +313,21 @@ And for has_many_attached:
290
313
  }
291
314
  ```
292
315
 
293
- # ACTIVESTORAGE ATTACHMENTS
316
+ # Activestorage Attachments
294
317
 
295
318
  For activestorage attachment support, the following two routes are added to models using activestorage:
296
319
 
297
320
  `/table_name/:id/attach/:attachment_name` and `/table_name/:id/unattach/:attachment_id`
298
321
 
299
- ## ATTACH: POST '/table_name/:id/attach/:attachment_name'
322
+ ## Attach
300
323
 
301
324
  The routes generated for the rest API are based on the naming provided in your ActiveRecord model when using activestorage.
302
325
 
303
326
  - Supports both has_one_attached & has_many_attached.
304
327
 
305
- In the articles example above, this would be: "/api/v1/articles/attach/feature_image"
328
+ In the articles example above, this would be:
329
+
330
+ POST "/api/v1/articles/attach/feature_image"
306
331
 
307
332
  The payload structure in this case needs only to be:
308
333
  ```
@@ -320,7 +345,9 @@ If successful, the response will be as follows:
320
345
  }
321
346
  ```
322
347
 
323
- ## UNATTACH: DELETE '/table_name/:id/unattach/:attachment_id'
348
+ ## Unattach
349
+
350
+ DELETE '/table_name/:id/unattach/:attachment_id'
324
351
 
325
352
  *\* Note, Response will fail if the attachment_id provided does not belong to the object.*
326
353
 
@@ -334,10 +361,10 @@ If successful, the response will be as follows:
334
361
  ```
335
362
 
336
363
 
337
-
338
-
339
364
  ## Contribution
340
365
  Here are some features in need of development.
341
- - Add way to "protect columns" (i.e. exclude columns from permitted params for model's update/create API points).
342
366
  - Support different popular attachment gems.
343
367
  - Add Locale fetching based on page-routes.
368
+ - Add standarized testing rspecs.
369
+ - Add support for switching activestorage sources
370
+ - Add support to allow user to provide any before_actions wanted.
@@ -3,7 +3,8 @@ module RestRails
3
3
  class DataController < ::ApplicationController
4
4
  include ApplicationHelper
5
5
  skip_before_action :verify_authenticity_token
6
- before_action :set_model, only: [:index, :show, :create, :update, :destroy, :fetch_column, :attach, :unattach]
6
+ before_action :verify_table_permissions!, only: [:create, :update, :destroy, :attach, :unattach]
7
+ before_action :set_model
7
8
  before_action :set_object, only: [:show, :update, :destroy, :fetch_column, :attach, :unattach]
8
9
 
9
10
  def index
@@ -36,7 +37,7 @@ module RestRails
36
37
  end
37
38
 
38
39
  def create
39
- @object = @empty_obj(model_params)
40
+ @object = @model.new(model_params)
40
41
 
41
42
  attach_files
42
43
  if @object.save
@@ -99,6 +100,7 @@ module RestRails
99
100
  # Take the tablename, and make the Model of the relative table_name
100
101
  @model = model_for(params[:table_name])
101
102
  @empty_obj = @model.new
103
+ p @empty_obj
102
104
  end
103
105
 
104
106
  def set_object
@@ -112,8 +114,6 @@ module RestRails
112
114
  return {} if params[mn].blank?
113
115
  # MAKE LIST OF THINGS TO PERMIT:
114
116
  arr = @model.attribute_names.map(&:to_sym)
115
- arr.delete(:created_at)
116
- arr.delete(:updated_at)
117
117
 
118
118
  # allow arrays for all columns for flexible where queries
119
119
  arr += arr.map do |attr|
@@ -159,25 +159,19 @@ module RestRails
159
159
  end
160
160
 
161
161
  def permitted_columns
162
- @columns = @model.attribute_names.map(&:to_sym)
162
+ p @empty_obj
163
+ @columns = columns_for(@empty_obj)
163
164
  @columns.delete(:id)
164
165
  @columns.delete(:created_at)
165
166
  @columns.delete(:updated_at)
166
167
 
167
- @columns.map! do |attr|
168
- new_val = permit_array?(attr) ? {attr=>[]} : attr
169
- new_val
170
- end
171
- permitted_attachments if RestRails.active_storage_attachments
172
- end
173
-
174
- def permitted_attachments
175
- file_set = attachments_for(@empty_obj)
176
- file_set += file_set.select{|x| permit_array?(x)}.map do |attr|
168
+ @columns += @columns.select{|x| permit_array?(x)}.map do |attr|
177
169
  {attr=>[]}
178
170
  end
171
+ end
179
172
 
180
- @columns = @columns + file_set
173
+ def verify_table_permissions!
174
+ verify_permitted!(params[:table_name].to_sym)
181
175
  end
182
176
  end
183
177
  end
@@ -58,8 +58,13 @@ module RestRails
58
58
  end
59
59
 
60
60
  def columns_for(ar_object)
61
- cols = ar_object.class.attribute_names.map(&:to_sym)
62
- cols += attachments_for(ar_object)
61
+ table = ar_object.class.table_name.to_sym
62
+ cols = ar_object.class.column_names.map(&:to_sym)
63
+ cols += attachments_for(ar_object) if RestRails.active_storage_attachments
64
+
65
+ return cols if RestRails.permit == :all || RestRails.permit[table] == :all
66
+
67
+ cols.select{|x| RestRails.permit[table].include?(x) }
63
68
  end
64
69
 
65
70
  # ==========================================================================
@@ -76,5 +81,13 @@ module RestRails
76
81
  # Take the tablename, and make the Model of the relative table_name
77
82
  table_name.classify.constantize # "users" => User
78
83
  end
84
+
85
+ def verify_permitted!(table)
86
+ if [:none, nil].include?(RestRails.permit[table])
87
+ raise RestRails::Error.new "NOT PERMITTED. Must add table to whitelisted params."
88
+ elsif !RestRails.permit.is_a?(Hash) && (RestRails.permit != :all)
89
+ raise RestRails::Error.new "RestRails initializer permit is not valid!"
90
+ end
91
+ end
79
92
  end
80
93
  end
@@ -4,6 +4,18 @@ RestRails.configure do |config|
4
4
  # set debug to true if you want to see loud errors in the server logs.
5
5
  config.debug = false
6
6
 
7
+ # ===============================================================
8
+ # IMPORTANT!
9
+ # Setup whitelist permissions for what db columns can be
10
+ # modified by the REST API
11
+ # ===============================================================
12
+ # config.permit = {
13
+ # users: :none,
14
+ # table_name: :all,
15
+ # other_table: [:col1, :col2, :col3]
16
+ # }
17
+
18
+ # ===============================================================
7
19
  # if you are using devise or another authentication system and want to
8
20
  # enforce the before_action `authenticate_user!`
9
21
  #
@@ -1,3 +1,3 @@
1
1
  module RestRails
2
- VERSION = '0.8.0'
2
+ VERSION = '0.9.0'
3
3
  end
data/lib/rest_rails.rb CHANGED
@@ -3,6 +3,7 @@ require "rest_rails/error"
3
3
 
4
4
  module RestRails
5
5
  mattr_accessor :debug, default: false
6
+ mattr_accessor :permit, default: :all
6
7
  mattr_accessor :authenticatable, default: false
7
8
  mattr_accessor :active_storage_attachments, default: true
8
9
  mattr_accessor :production_domain, default: nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergio Rivas