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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +853 -0
  4. data/Rakefile +29 -0
  5. data/app/params/account_params.rb.example +38 -0
  6. data/app/params/application_params.rb +16 -0
  7. data/lib/durable_parameters/adapters/hanami.rb +138 -0
  8. data/lib/durable_parameters/adapters/rage.rb +124 -0
  9. data/lib/durable_parameters/adapters/rails.rb +280 -0
  10. data/lib/durable_parameters/adapters/sinatra.rb +91 -0
  11. data/lib/durable_parameters/core/application_params.rb +334 -0
  12. data/lib/durable_parameters/core/configuration.rb +83 -0
  13. data/lib/durable_parameters/core/forbidden_attributes_protection.rb +48 -0
  14. data/lib/durable_parameters/core/parameters.rb +643 -0
  15. data/lib/durable_parameters/core/params_registry.rb +110 -0
  16. data/lib/durable_parameters/core.rb +15 -0
  17. data/lib/durable_parameters/log_subscriber.rb +34 -0
  18. data/lib/durable_parameters/railtie.rb +65 -0
  19. data/lib/durable_parameters/version.rb +7 -0
  20. data/lib/durable_parameters.rb +41 -0
  21. data/lib/generators/rails/USAGE +12 -0
  22. data/lib/generators/rails/durable_parameters_controller_generator.rb +17 -0
  23. data/lib/generators/rails/templates/controller.rb +94 -0
  24. data/lib/legacy/action_controller/application_params.rb +235 -0
  25. data/lib/legacy/action_controller/parameters.rb +524 -0
  26. data/lib/legacy/action_controller/params_registry.rb +108 -0
  27. data/lib/legacy/active_model/forbidden_attributes_protection.rb +40 -0
  28. data/test/action_controller_required_params_test.rb +36 -0
  29. data/test/action_controller_tainted_params_test.rb +29 -0
  30. data/test/active_model_mass_assignment_taint_protection_test.rb +25 -0
  31. data/test/application_params_array_test.rb +245 -0
  32. data/test/application_params_edge_cases_test.rb +361 -0
  33. data/test/application_params_test.rb +893 -0
  34. data/test/controller_generator_test.rb +31 -0
  35. data/test/core_parameters_test.rb +2376 -0
  36. data/test/durable_parameters_test.rb +115 -0
  37. data/test/enhanced_error_messages_test.rb +120 -0
  38. data/test/gemfiles/Gemfile.rails-3.0.x +14 -0
  39. data/test/gemfiles/Gemfile.rails-3.1.x +14 -0
  40. data/test/gemfiles/Gemfile.rails-3.2.x +14 -0
  41. data/test/log_on_unpermitted_params_test.rb +49 -0
  42. data/test/metadata_validation_test.rb +294 -0
  43. data/test/multi_parameter_attributes_test.rb +38 -0
  44. data/test/parameters_core_methods_test.rb +503 -0
  45. data/test/parameters_integration_test.rb +553 -0
  46. data/test/parameters_permit_test.rb +491 -0
  47. data/test/parameters_require_test.rb +9 -0
  48. data/test/parameters_taint_test.rb +98 -0
  49. data/test/params_registry_concurrency_test.rb +422 -0
  50. data/test/params_registry_test.rb +112 -0
  51. data/test/permit_by_model_test.rb +227 -0
  52. data/test/raise_on_unpermitted_params_test.rb +32 -0
  53. data/test/test_helper.rb +38 -0
  54. data/test/transform_params_edge_cases_test.rb +526 -0
  55. data/test/transformation_test.rb +360 -0
  56. 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
@@ -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 }