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 +4 -4
- data/README.md +42 -15
- data/app/controllers/rest_rails/data_controller.rb +10 -16
- data/app/helpers/rest_rails/application_helper.rb +15 -2
- data/lib/generators/rest_rails/templates/rest_rails.rb +12 -0
- data/lib/rest_rails/version.rb +1 -1
- data/lib/rest_rails.rb +1 -0
- 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: 652e20dd610f1f6647f5d4dadac3d16a6d782bc0dc9765993d8bd064eb571e4e
|
4
|
+
data.tar.gz: 4fcfb8bef731b3e1067f033d1d62eee2f31478e7f737673cc1100d222f491a69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
#
|
78
|
+
# Using the REST API
|
56
79
|
|
57
|
-
##
|
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
|
-
##
|
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
|
-
##
|
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
|
-
##
|
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
|
-
##
|
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
|
-
##
|
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
|
-
#
|
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
|
-
##
|
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:
|
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
|
-
##
|
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 :
|
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 = @
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
62
|
-
cols
|
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
|
#
|
data/lib/rest_rails/version.rb
CHANGED
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
|