durable_parameters 0.2.3
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +853 -0
- data/Rakefile +29 -0
- data/app/params/account_params.rb.example +38 -0
- data/app/params/application_params.rb +16 -0
- data/lib/durable_parameters/adapters/hanami.rb +138 -0
- data/lib/durable_parameters/adapters/rage.rb +124 -0
- data/lib/durable_parameters/adapters/rails.rb +280 -0
- data/lib/durable_parameters/adapters/sinatra.rb +91 -0
- data/lib/durable_parameters/core/application_params.rb +334 -0
- data/lib/durable_parameters/core/configuration.rb +83 -0
- data/lib/durable_parameters/core/forbidden_attributes_protection.rb +48 -0
- data/lib/durable_parameters/core/parameters.rb +643 -0
- data/lib/durable_parameters/core/params_registry.rb +110 -0
- data/lib/durable_parameters/core.rb +15 -0
- data/lib/durable_parameters/log_subscriber.rb +34 -0
- data/lib/durable_parameters/railtie.rb +65 -0
- data/lib/durable_parameters/version.rb +7 -0
- data/lib/durable_parameters.rb +41 -0
- data/lib/generators/rails/USAGE +12 -0
- data/lib/generators/rails/durable_parameters_controller_generator.rb +17 -0
- data/lib/generators/rails/templates/controller.rb +94 -0
- data/lib/legacy/action_controller/application_params.rb +235 -0
- data/lib/legacy/action_controller/parameters.rb +524 -0
- data/lib/legacy/action_controller/params_registry.rb +108 -0
- data/lib/legacy/active_model/forbidden_attributes_protection.rb +40 -0
- data/test/action_controller_required_params_test.rb +36 -0
- data/test/action_controller_tainted_params_test.rb +29 -0
- data/test/active_model_mass_assignment_taint_protection_test.rb +25 -0
- data/test/application_params_array_test.rb +245 -0
- data/test/application_params_edge_cases_test.rb +361 -0
- data/test/application_params_test.rb +893 -0
- data/test/controller_generator_test.rb +31 -0
- data/test/core_parameters_test.rb +2376 -0
- data/test/durable_parameters_test.rb +115 -0
- data/test/enhanced_error_messages_test.rb +120 -0
- data/test/gemfiles/Gemfile.rails-3.0.x +14 -0
- data/test/gemfiles/Gemfile.rails-3.1.x +14 -0
- data/test/gemfiles/Gemfile.rails-3.2.x +14 -0
- data/test/log_on_unpermitted_params_test.rb +49 -0
- data/test/metadata_validation_test.rb +294 -0
- data/test/multi_parameter_attributes_test.rb +38 -0
- data/test/parameters_core_methods_test.rb +503 -0
- data/test/parameters_integration_test.rb +553 -0
- data/test/parameters_permit_test.rb +491 -0
- data/test/parameters_require_test.rb +9 -0
- data/test/parameters_taint_test.rb +98 -0
- data/test/params_registry_concurrency_test.rb +422 -0
- data/test/params_registry_test.rb +112 -0
- data/test/permit_by_model_test.rb +227 -0
- data/test/raise_on_unpermitted_params_test.rb +32 -0
- data/test/test_helper.rb +38 -0
- data/test/transform_params_edge_cases_test.rb +526 -0
- data/test/transformation_test.rb +360 -0
- metadata +223 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class TransformParamsTest < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
ActionController::ParamsRegistry.clear!
|
|
6
|
+
|
|
7
|
+
@user_params_class = Class.new(ActionController::ApplicationParams) do
|
|
8
|
+
def self.name
|
|
9
|
+
'UserParams'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
allow :first_name
|
|
13
|
+
allow :last_name
|
|
14
|
+
allow :email
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
ActionController::ParamsRegistry.register('User', @user_params_class)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def teardown
|
|
21
|
+
ActionController::ParamsRegistry.clear!
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_transform_params_with_auto_inferred_class
|
|
25
|
+
params = ActionController::Parameters.new(
|
|
26
|
+
user: {
|
|
27
|
+
first_name: 'John',
|
|
28
|
+
last_name: 'Doe',
|
|
29
|
+
email: 'john@example.com',
|
|
30
|
+
is_admin: true
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
permitted = params.require(:user).transform_params()
|
|
35
|
+
|
|
36
|
+
assert_equal 'John', permitted[:first_name]
|
|
37
|
+
assert_equal 'Doe', permitted[:last_name]
|
|
38
|
+
assert_equal 'john@example.com', permitted[:email]
|
|
39
|
+
assert_nil permitted[:is_admin]
|
|
40
|
+
assert permitted.permitted?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_transform_params_with_explicit_params_class
|
|
44
|
+
params = ActionController::Parameters.new(
|
|
45
|
+
user: {
|
|
46
|
+
first_name: 'John',
|
|
47
|
+
last_name: 'Doe',
|
|
48
|
+
email: 'john@example.com',
|
|
49
|
+
is_admin: true
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
permitted = params.require(:user).transform_params(@user_params_class)
|
|
54
|
+
|
|
55
|
+
assert_equal 'John', permitted[:first_name]
|
|
56
|
+
assert_equal 'Doe', permitted[:last_name]
|
|
57
|
+
assert_equal 'john@example.com', permitted[:email]
|
|
58
|
+
assert_nil permitted[:is_admin]
|
|
59
|
+
assert permitted.permitted?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def test_transform_params_with_current_user_always_allowed
|
|
63
|
+
params = ActionController::Parameters.new(
|
|
64
|
+
user: {
|
|
65
|
+
first_name: 'Jane',
|
|
66
|
+
last_name: 'Smith',
|
|
67
|
+
email: 'jane@example.com'
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
current_user = Object.new # Mock user object
|
|
72
|
+
|
|
73
|
+
# current_user is always allowed without needing to be declared
|
|
74
|
+
permitted = params.require(:user).transform_params(current_user: current_user)
|
|
75
|
+
|
|
76
|
+
assert_equal 'Jane', permitted[:first_name]
|
|
77
|
+
assert_equal 'Smith', permitted[:last_name]
|
|
78
|
+
assert_equal 'jane@example.com', permitted[:email]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_transform_params_with_declared_metadata
|
|
82
|
+
test_params_class = Class.new(ActionController::ApplicationParams) do
|
|
83
|
+
def self.name
|
|
84
|
+
'AccountParams'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
allow :first_name
|
|
88
|
+
allow :last_name
|
|
89
|
+
allow :email
|
|
90
|
+
|
|
91
|
+
# Declare allowed metadata
|
|
92
|
+
metadata :ip_address, :role
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
ActionController::ParamsRegistry.register('Account', test_params_class)
|
|
96
|
+
|
|
97
|
+
params = ActionController::Parameters.new(
|
|
98
|
+
account: {
|
|
99
|
+
first_name: 'Jane',
|
|
100
|
+
last_name: 'Smith',
|
|
101
|
+
email: 'jane@example.com'
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Can pass declared metadata along with current_user
|
|
106
|
+
permitted = params.require(:account).transform_params(
|
|
107
|
+
current_user: Object.new,
|
|
108
|
+
ip_address: '127.0.0.1',
|
|
109
|
+
role: :admin
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
assert_equal 'Jane', permitted[:first_name]
|
|
113
|
+
assert_equal 'Smith', permitted[:last_name]
|
|
114
|
+
assert_equal 'jane@example.com', permitted[:email]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_transform_params_raises_on_undeclared_metadata
|
|
118
|
+
params = ActionController::Parameters.new(
|
|
119
|
+
user: {
|
|
120
|
+
first_name: 'Jane',
|
|
121
|
+
last_name: 'Smith',
|
|
122
|
+
email: 'jane@example.com'
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Should raise error when passing metadata that hasn't been declared
|
|
127
|
+
error = assert_raises(ArgumentError) do
|
|
128
|
+
params.require(:user).transform_params(
|
|
129
|
+
current_user: Object.new,
|
|
130
|
+
ip_address: '127.0.0.1' # Not declared in UserParams
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
assert_includes error.message, 'ip_address'
|
|
135
|
+
assert_includes error.message, 'metadata :ip_address'
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def test_transform_params_with_additional_attrs
|
|
139
|
+
params = ActionController::Parameters.new(
|
|
140
|
+
user: {
|
|
141
|
+
first_name: 'John',
|
|
142
|
+
last_name: 'Doe',
|
|
143
|
+
email: 'john@example.com',
|
|
144
|
+
age: 30
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
permitted = params.require(:user).transform_params(additional_attrs: [:age])
|
|
149
|
+
|
|
150
|
+
assert_equal 'John', permitted[:first_name]
|
|
151
|
+
assert_equal 30, permitted[:age]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def test_transform_params_with_action_filter
|
|
155
|
+
test_params_class = Class.new(ActionController::ApplicationParams) do
|
|
156
|
+
def self.name
|
|
157
|
+
'PostParams'
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
allow :title
|
|
161
|
+
allow :body
|
|
162
|
+
allow :published, only: :create
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
ActionController::ParamsRegistry.register('Post', test_params_class)
|
|
166
|
+
|
|
167
|
+
# With action: :create, published should be permitted
|
|
168
|
+
params = ActionController::Parameters.new(
|
|
169
|
+
post: {
|
|
170
|
+
title: 'Test',
|
|
171
|
+
body: 'Content',
|
|
172
|
+
published: true
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
permitted = params.require(:post).transform_params(action: :create)
|
|
176
|
+
assert_equal 'Test', permitted[:title]
|
|
177
|
+
assert_equal 'Content', permitted[:body]
|
|
178
|
+
assert_equal true, permitted[:published]
|
|
179
|
+
|
|
180
|
+
# With action: :update, published should not be permitted
|
|
181
|
+
params2 = ActionController::Parameters.new(
|
|
182
|
+
post: {
|
|
183
|
+
title: 'Test',
|
|
184
|
+
body: 'Content',
|
|
185
|
+
published: true
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
permitted2 = params2.require(:post).transform_params(action: :update)
|
|
189
|
+
assert_equal 'Test', permitted2[:title]
|
|
190
|
+
assert_equal 'Content', permitted2[:body]
|
|
191
|
+
assert_nil permitted2[:published]
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def test_transform_params_with_unregistered_model
|
|
195
|
+
params = ActionController::Parameters.new(
|
|
196
|
+
nonexistent: {
|
|
197
|
+
name: 'Test',
|
|
198
|
+
value: 123
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
permitted = params.require(:nonexistent).transform_params()
|
|
203
|
+
|
|
204
|
+
# Should return empty permitted params
|
|
205
|
+
assert permitted.permitted?
|
|
206
|
+
assert_nil permitted[:name]
|
|
207
|
+
assert_nil permitted[:value]
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Test backwards compatibility with permit_by_model
|
|
211
|
+
def test_permit_by_model_still_works_for_backwards_compatibility
|
|
212
|
+
params = ActionController::Parameters.new(
|
|
213
|
+
first_name: 'John',
|
|
214
|
+
last_name: 'Doe',
|
|
215
|
+
email: 'john@example.com',
|
|
216
|
+
is_admin: true
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
permitted = params.permit_by_model(:user)
|
|
220
|
+
|
|
221
|
+
assert_equal 'John', permitted[:first_name]
|
|
222
|
+
assert_equal 'Doe', permitted[:last_name]
|
|
223
|
+
assert_equal 'john@example.com', permitted[:email]
|
|
224
|
+
assert_nil permitted[:is_admin]
|
|
225
|
+
assert permitted.permitted?
|
|
226
|
+
end
|
|
227
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class RaiseOnUnpermittedParamsTest < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
ActionController::Parameters.action_on_unpermitted_parameters = :raise
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def teardown
|
|
9
|
+
ActionController::Parameters.action_on_unpermitted_parameters = false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_raises_on_unexpected_params
|
|
13
|
+
params = ActionController::Parameters.new({
|
|
14
|
+
:book => { :pages => 65 },
|
|
15
|
+
:fishing => "Turnips"
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
assert_raises(ActionController::UnpermittedParameters) do
|
|
19
|
+
params.permit(:book => [:pages])
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_raises_on_unexpected_nested_params
|
|
24
|
+
params = ActionController::Parameters.new({
|
|
25
|
+
:book => { :pages => 65, :title => "Green Cats and where to find then." }
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
assert_raises(ActionController::UnpermittedParameters) do
|
|
29
|
+
params.permit(:book => [:pages])
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Configure Rails Environment
|
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
|
3
|
+
|
|
4
|
+
# Ruby 3.3 compatibility: File.exists? is deprecated, add alias for older Rails
|
|
5
|
+
unless File.respond_to?(:exists?)
|
|
6
|
+
class << File
|
|
7
|
+
alias_method :exists?, :exist?
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
require 'minitest/autorun'
|
|
12
|
+
require 'rails'
|
|
13
|
+
|
|
14
|
+
class FakeApplication < Rails::Application; end
|
|
15
|
+
|
|
16
|
+
Rails.application = FakeApplication
|
|
17
|
+
Rails.configuration.action_controller = ActiveSupport::OrderedOptions.new
|
|
18
|
+
|
|
19
|
+
# Define routes for controller tests
|
|
20
|
+
Rails.application.routes.draw do
|
|
21
|
+
post 'people/create' => 'people#create'
|
|
22
|
+
post 'people/create_with_permit' => 'people#create_with_permit'
|
|
23
|
+
post 'books/create' => 'books#create'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
require 'durable_parameters'
|
|
27
|
+
|
|
28
|
+
# Manually setup Rails adapter since we're not going through full Rails initialization
|
|
29
|
+
StrongParameters::Adapters::Rails.setup!
|
|
30
|
+
|
|
31
|
+
# Note: ActionController::Base and related test infrastructure is loaded
|
|
32
|
+
# only when needed by controller-specific tests to avoid dependency issues.
|
|
33
|
+
# See controller_test_helper.rb for controller test setup.
|
|
34
|
+
|
|
35
|
+
ActionController::Parameters.action_on_unpermitted_parameters = false
|
|
36
|
+
|
|
37
|
+
# Load support files
|
|
38
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|