stronger_parameters 2.7.0 → 2.8.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 +62 -0
- data/lib/stronger_parameters/controller_support/permitted_parameters.rb +159 -0
- data/lib/stronger_parameters/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0765498e474bdda1bbd86952faeb949bb8dee68d
|
4
|
+
data.tar.gz: 552b525dd274336986326681a21a334139bfbb25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1317839557a9579b3710b15c314de07a02766e6ac511a84ef3b98fe3dd8fe8dd5c00c442d3c952d67f0287cc57589944eac80e41fe2e2eaa27101f8bb612f06
|
7
|
+
data.tar.gz: 5abbe1cc2b805bf72ff355c4d79de711bb09c18aaa1a4e97aceaf13d4e7bfe8c321d890f7d118fcef69036fb19ee5613f86dce9cfa2065c7e1f5d6f6c47d8e74
|
data/README.md
CHANGED
@@ -158,6 +158,68 @@ Just want to log violations in production:
|
|
158
158
|
ActionController::Parameters.action_on_invalid_parameters = :log
|
159
159
|
```
|
160
160
|
|
161
|
+
## Controller support (compatible with Rails 3 and 4, untested on Rails 5)
|
162
|
+
|
163
|
+
Include `PermittedParameters` into a controller to force the developer
|
164
|
+
to explicitly permit params for every action.
|
165
|
+
|
166
|
+
Examples:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
class TestController < ApplicationController
|
170
|
+
include StrongerParameters::ControllerSupport::PermittedParameters
|
171
|
+
|
172
|
+
permitted_parameters :all, locale: Parameters.string # permit :locale in all actions for this controller
|
173
|
+
|
174
|
+
permitted_parameters :show, id: Parameters.integer
|
175
|
+
def show
|
176
|
+
end
|
177
|
+
|
178
|
+
permitted_parameters :create, topic: { forum: { id: Parameters.integer } }
|
179
|
+
def create
|
180
|
+
end
|
181
|
+
|
182
|
+
permitted_parameters :index, {} # no parameters permitted
|
183
|
+
def index
|
184
|
+
end
|
185
|
+
|
186
|
+
permitted_parameters :update, :anything # all parameters permitted, use when migrating old controllers/actions
|
187
|
+
def update
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
|
192
|
+
### Log only mode
|
193
|
+
|
194
|
+
Just want to log violations in production, let all params pass through:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
class MyController < ApplicationController
|
198
|
+
log_unpermitted_parameters! if Rails.env.production? # Still want other environments to raise
|
199
|
+
|
200
|
+
permitted_parameters :update, user: { name: Parameters.string }
|
201
|
+
def update
|
202
|
+
end
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
### Notifying users about unpermitted params
|
207
|
+
|
208
|
+
Add headers to all requests that have unpermitted params:
|
209
|
+
|
210
|
+
```Ruby
|
211
|
+
# config/application.rb
|
212
|
+
config.stronger_parameters_violation_header = 'X-StrongerParameters-API-Warn'
|
213
|
+
```
|
214
|
+
|
215
|
+
```shell
|
216
|
+
curl -I 'http://localhost/api/users/1.json' -X POST -d '{ "user": { "id": 1 } }'
|
217
|
+
=> HTTP/1.1 200 OK
|
218
|
+
=> ...
|
219
|
+
=> X-StrongerParameters-API-Warn: Removed restricted keys ["user.id"] from parameters
|
220
|
+
```
|
221
|
+
|
222
|
+
|
161
223
|
## Types
|
162
224
|
|
163
225
|
| Syntax | (Simplified) Definition |
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'stronger_parameters/constraints'
|
2
|
+
|
3
|
+
module StrongerParameters
|
4
|
+
module ControllerSupport
|
5
|
+
module PermittedParameters
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend ClassMethods
|
8
|
+
if klass.respond_to?(:before_action)
|
9
|
+
klass.before_action :permit_parameters
|
10
|
+
else
|
11
|
+
klass.before_filter :permit_parameters
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class PermittedParametersHash < Hash
|
16
|
+
def initialize(other = nil)
|
17
|
+
super()
|
18
|
+
merge!(other) unless other.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def merge!(other)
|
22
|
+
other.each do |key, value|
|
23
|
+
value = sugar(value)
|
24
|
+
|
25
|
+
if value.is_a?(StrongerParameters::Constraint)
|
26
|
+
self[key] = value
|
27
|
+
else
|
28
|
+
self[key] ||= self.class.new
|
29
|
+
self[key].merge!(value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def merge(other)
|
37
|
+
dup.merge!(other)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def sugar(value)
|
43
|
+
case value
|
44
|
+
when Array
|
45
|
+
ActionController::Parameters.array(*value.map { |v| sugar(v) })
|
46
|
+
when Hash
|
47
|
+
constraints = value.each_with_object({}) do |(key, v), memo|
|
48
|
+
memo[key] = sugar(v)
|
49
|
+
end
|
50
|
+
ActionController::Parameters.map(constraints)
|
51
|
+
else
|
52
|
+
value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
DEFAULT_PERMITTED = PermittedParametersHash.new(
|
58
|
+
controller: ActionController::Parameters.anything,
|
59
|
+
action: ActionController::Parameters.anything,
|
60
|
+
format: ActionController::Parameters.anything,
|
61
|
+
authenticity_token: ActionController::Parameters.string
|
62
|
+
)
|
63
|
+
|
64
|
+
module ClassMethods
|
65
|
+
def self.extended(base)
|
66
|
+
base.send :class_attribute, :log_unpermitted_parameters, instance_accessor: false
|
67
|
+
end
|
68
|
+
|
69
|
+
def log_unpermitted_parameters!
|
70
|
+
self.log_unpermitted_parameters = true
|
71
|
+
end
|
72
|
+
|
73
|
+
def permitted_parameters(action, permitted)
|
74
|
+
if permit_parameters[action] == :anything && permitted != :anything
|
75
|
+
raise ArgumentError, "#{self}/#{action} can not add to :anything"
|
76
|
+
end
|
77
|
+
|
78
|
+
permit_parameters.deep_merge!(action => permitted)
|
79
|
+
end
|
80
|
+
|
81
|
+
def permitted_parameters_for(action)
|
82
|
+
unless for_action = permit_parameters[action]
|
83
|
+
location = instance_method(action).source_location
|
84
|
+
raise KeyError, "Action #{action} for #{self} does not have any permitted parameters (#{location.join(":")})"
|
85
|
+
end
|
86
|
+
return :anything if for_action == :anything
|
87
|
+
permit_parameters[:all].merge(for_action)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def permit_parameters
|
93
|
+
@permit_parameters ||= if superclass.respond_to?(:permit_parameters, true)
|
94
|
+
superclass.send(:permit_parameters).deep_dup
|
95
|
+
else
|
96
|
+
{ all: DEFAULT_PERMITTED.dup }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def permit_parameters
|
104
|
+
action = params[:action].to_sym
|
105
|
+
permitted = self.class.permitted_parameters_for(action)
|
106
|
+
|
107
|
+
if permitted == :anything
|
108
|
+
Rails.logger.warn("#{params[:controller]}/#{params[:action]} does not filter parameters")
|
109
|
+
return
|
110
|
+
end
|
111
|
+
|
112
|
+
permitted_params = without_invalid_parameter_exceptions { params.permit(permitted) }
|
113
|
+
unpermitted_keys = flat_keys(params) - flat_keys(permitted_params)
|
114
|
+
log_unpermitted = self.class.log_unpermitted_parameters
|
115
|
+
|
116
|
+
show_unpermitted_keys(unpermitted_keys, log_unpermitted)
|
117
|
+
|
118
|
+
return if log_unpermitted
|
119
|
+
|
120
|
+
params.replace(permitted_params)
|
121
|
+
params.permit!
|
122
|
+
request.params.replace(permitted_params)
|
123
|
+
|
124
|
+
logged_params = request.send(:parameter_filter).filter(permitted_params) # Removing passwords, etc
|
125
|
+
Rails.logger.info(" Filtered Parameters: #{logged_params.inspect}")
|
126
|
+
end
|
127
|
+
|
128
|
+
def show_unpermitted_keys(unpermitted_keys, log_unpermitted)
|
129
|
+
return if unpermitted_keys.empty?
|
130
|
+
|
131
|
+
log_prefix = (log_unpermitted ? 'Found' : 'Removed')
|
132
|
+
message = "#{log_prefix} restricted keys #{unpermitted_keys.inspect} from parameters according to permitted list"
|
133
|
+
|
134
|
+
header = Rails.configuration.stronger_parameters_violation_header if Rails.configuration.respond_to?(:stronger_parameters_violation_header)
|
135
|
+
response.headers[header] = message if response && header
|
136
|
+
|
137
|
+
Rails.logger.info(" #{message}")
|
138
|
+
end
|
139
|
+
|
140
|
+
def without_invalid_parameter_exceptions
|
141
|
+
if self.class.log_unpermitted_parameters
|
142
|
+
begin
|
143
|
+
old = ActionController::Parameters.action_on_invalid_parameters
|
144
|
+
ActionController::Parameters.action_on_invalid_parameters = :log
|
145
|
+
yield
|
146
|
+
ensure
|
147
|
+
ActionController::Parameters.action_on_invalid_parameters = old
|
148
|
+
end
|
149
|
+
else
|
150
|
+
yield
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def flat_keys(hash)
|
155
|
+
hash.flat_map { |k, v| v.is_a?(Hash) ? flat_keys(v).map { |x| "#{k}.#{x}" }.push(k) : k }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stronger_parameters
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mick Staugaard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -168,6 +168,7 @@ files:
|
|
168
168
|
- lib/stronger_parameters/constraints/nil_string_constraint.rb
|
169
169
|
- lib/stronger_parameters/constraints/regexp_constraint.rb
|
170
170
|
- lib/stronger_parameters/constraints/string_constraint.rb
|
171
|
+
- lib/stronger_parameters/controller_support/permitted_parameters.rb
|
171
172
|
- lib/stronger_parameters/errors.rb
|
172
173
|
- lib/stronger_parameters/parameters.rb
|
173
174
|
- lib/stronger_parameters/version.rb
|
@@ -191,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
191
192
|
version: '0'
|
192
193
|
requirements: []
|
193
194
|
rubyforge_project:
|
194
|
-
rubygems_version: 2.5.1
|
195
|
+
rubygems_version: 2.4.5.1
|
195
196
|
signing_key:
|
196
197
|
specification_version: 4
|
197
198
|
summary: Type checking and type casting of parameters for Action Pack
|