rest_rails 0.8.0 → 0.9.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/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
|