auto_strong_parameters 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7957f41175cec758139ef39f6b1b1889b7d164c51b658cf09ad58f9a14fc8b9e
4
+ data.tar.gz: a5775efa5e7ad60032c7915832bc86f5119bf3496e9a16269a922c6ab696ee08
5
+ SHA512:
6
+ metadata.gz: 68b0628b21442f52584f689266f736e62ce810ecfb629d94208e8ea72d531c210243e0952ffcaca46bbfbe579a0cfb5ae37aebbf83910e3817ed7183e593760d
7
+ data.tar.gz: 71a53c2f1d3ee226d73ea6f8f8467f76e10b35b2cd02e6cd18b5241f53c13077f038abacc2286ee5fba06d65361b6cd33c3cd6110f720885699a096498c71c20
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # Auto Strong Parameters
2
+
3
+ Auto Strong Parameters detects the fields included in a form and automatically permits them in the controller. You no longer need to manually enumerate the params you've submitted. You can fall back to standard Strong Parameters when you need custom behavior.
4
+
5
+ Rails 4.0 introduced Rails developers to the world of Strong Parameters. This gem is an extension to the model that Strong Parameters introduced, intended to reduce or eliminate the busy work that Strong Paramters introduced. As Giles Bowkett wrote, "tedious, repetitive work is for computers to do."
6
+
7
+ - :white_check_mark: Seamless integration: replace `require(key).permit` calls with `auto_permit!(key)`
8
+ - :safety_vest: Safe from malicious tampering due to message signing
9
+ - :trophy: Graceful upgrade and fallback to standard Strong Parameters
10
+ - :bow: No more busy work enumerating permitted parameters twice
11
+
12
+ ## How it works (TL;DR)
13
+
14
+ ```ruby
15
+ # Replace this...
16
+ user_params = params.require(:user).permit(:first_name, :email)
17
+
18
+ # ...with this
19
+ user_params = params.auto_permit!(:user)
20
+ ```
21
+
22
+ ## How it works
23
+
24
+ Before:
25
+ ```ruby
26
+
27
+ # View
28
+ <%= form_with @user do |f| %>
29
+ First name: <%= f.text_field :first_name %>
30
+ Email: <%= f.email_field :email %>
31
+ <% end %>
32
+
33
+
34
+ # Controller
35
+ user_params = params.require(:user).permit(:first_name, :email)
36
+ # => { first_name: "Dave", email: "dave@example.com }
37
+ @user = User.create(user_params)
38
+ ```
39
+
40
+ After:
41
+
42
+ ```ruby
43
+ # View - unchanged
44
+ <%= form_with @user do |f| %>
45
+ First name: <%= f.text_field :first_name %>
46
+ Email: <%= f.email_field :email %>
47
+ <% end %>
48
+
49
+
50
+ # Controller - no enumeration required, your form dictates what is allowed
51
+ user_params = params.auto_permit!(:user)
52
+ # => { first_name: "Dave", email: "dave@example.com }
53
+ @user = User.create(user_params)
54
+ ```
55
+
56
+
57
+ ## How to use
58
+
59
+ Add to your Gemfile, `bundle install` and go.
60
+
61
+ ```ruby
62
+ gem 'auto_strong_parameters'
63
+ ```
64
+
65
+ ## Motivation
66
+
67
+ The Rails 2.x design of including permitted attributes in the model was a limited design. Models could be updated by users of different roles and having a single list was too restrictive.
68
+
69
+ Strong Parameters moved permitted attribute assertions from the model to the controller. To this day, parameters are authorized in the controllers they are submitted to. This change was for the better because it meant that each controller could assert its own set of parameters.
70
+
71
+ Strong Parameters still has the problem that multiple forms can submit to a single controller action. This issues means developers must implement controller-side configuration and know where each submission is coming from so that the correct parameters are authorized for all allowed situations. Additionally, there is fundamentally always double entry of what parameters you want to save - once by adding an input to your form and once again in the controller.
72
+
73
+ This design suggests that we can go one step further. Parameters are literally setup when you write your form code in your view. Each `f.text_field` or `f.number_field` says that you want that parameter in the form and accepted by the server. The form itself is the documentation as to what parameters can be submitted.
74
+
75
+ The natural solution is for the framework to handle authorizing the parameters that the developer already told it to put in the form.
76
+
77
+ ## Compatibility
78
+
79
+ Official support is currently set for all supported Rails releases as well as stable releases maintained by Rails LTS. There is no separate branch for separate versions, it is a goal keep this gem compatible for the life of Strong Parameters (Rails 4.0 - present).
80
+
81
+ - Ruby 2.7+, but should work fine with Ruby 2.0+
82
+ - Rails 4.2, 5.2, 6.0+
83
+
84
+ ### Form Builders
85
+
86
+ Auto Strong Parameters currently only supports the built-in Rails form builder class. If you use a different form builder and would like to see it supported, open a ticket, or better yet, write it and contribute back!
87
+
88
+ ### Unofficial compatibility
89
+
90
+ Our gemspec dictates Rails 4.0+ support but we do not test versions 4.0, 4.1, 5.0, or 5.1. It may work on those versions but it is not officially supported. This is a "use at your own risk" allowance - you should seriously reconsider running Rails 4.0/4.1 and 5.0/5.1 because they do not receive security updates or attention from official sources or private companies at all.
91
+
92
+ ### Why support Rails 4+?
93
+
94
+ There are thousands of Rails apps on old versions of Rails maintained by small teams that are unable to perform version upgrades. This gem aims to help make working with Strong Parameters easier and more seamless - one less headache when considering whether and when to upgrade. This is one way we can help relieve the upgrade and maintenance burden for folks on old versions of Rails.
95
+
96
+ Long-term support for non-officially-supported versions of Rails is offered by [Rails LTS](https://railslts.com) (no official affiliation, just a happy customer). Since Rails LTS is the only way that you can get these old versions of Rails to work with current Ruby versions, this gem is tested against them rather than the final releases from [rails/rails](https://github.com/rails/rails). In order to successfully run all our tests, you may need a license to get a copy of Rails LTS 4.2.
97
+
98
+ All that said, AutoStrongParameters should work fine with standard Rails 4.2 even if you are running an EOL version of Ruby.
99
+
100
+
101
+ ## Contributing
102
+
103
+ Contributions are welcome! If you use it and it doesn't work for you, please open an issue! If it DOES work for you, also let me know!
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require 'appraisal'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.pattern = "test/**/*_test.rb"
8
+ end
9
+
10
+ desc "Run tests"
11
+ task default: :test
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AutoStrongParameters::AutoFormParams
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ attr_reader :_asp_fields
8
+ end
9
+
10
+ ASP_NAME_REGEX = /\sname=\"(.+?)\"/
11
+ ASP_DIGIT_REGEX = /\[\d+\]/
12
+
13
+ TRACKED_FIELDS = %w(
14
+ search_field telephone_field date_field time_field datetime_field
15
+ month_field week_field url_field email_field number_field range_field
16
+ file_field password_field text_area text_field radio_button
17
+ )
18
+
19
+ TRACKED_FIELDS.each do |name|
20
+ module_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
21
+ def #{name}(*args)
22
+ super.tap do |res|
23
+ _asp_track_field(res)
24
+ end
25
+ end
26
+ RUBY_EVAL
27
+ end
28
+
29
+ private
30
+
31
+ def _asp_track_field(field)
32
+ @_asp_fields ||= []
33
+ @_asp_fields << field.match(ASP_NAME_REGEX)[1].gsub(ASP_DIGIT_REGEX, '[]')
34
+ end
35
+
36
+ # Generate a hidden input with the signed value of the params shape for this
37
+ # form. Append to the form.
38
+ def _asp_hidden_tag
39
+ if _asp_fields.present?
40
+ # puts "========= Adding tag =========="
41
+ # puts _asp_fields.inspect
42
+ name = AutoStrongParameters.asp_message_key
43
+ to_sign = asp_fields_to_shape
44
+ signature = AutoStrongParameters.verifier.generate(to_sign)
45
+
46
+ "<input type='hidden' name='#{name}' value='#{signature}' />".html_safe
47
+ else
48
+ ""
49
+ end
50
+ end
51
+
52
+ # This implementation is taken from Rails 7.0 but is largely the same as the
53
+ # version found in Rails 4.2. Since Rails doesn't give us a nice hook to add
54
+ # in our functionality, we do it by bringing in the full method and
55
+ # augmenting it here.
56
+ def form_tag_with_body(html_options, content)
57
+ output = form_tag_html(html_options)
58
+ output << content.to_s if content
59
+ output << _asp_hidden_tag
60
+ output.safe_concat("</form>")
61
+ end
62
+
63
+ # Concatenate all form element "name" values into a valid query string, parse
64
+ # it with Rack, and then convert to a Strong Parameters "shape" to be signed
65
+ # and sent to the server.
66
+ def asp_fields_to_shape
67
+ AutoStrongParameters.to_strong_params_shape(
68
+ Rack::Utils.parse_nested_query(_asp_fields.join("=&") + "=")
69
+ )
70
+ end
71
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AutoStrongParameters
4
+ module AutoPermit
5
+ def auto_permit!(key)
6
+ shape = asp_auto_permitted_params(key)
7
+
8
+ require(key).permit(shape[key])
9
+ end
10
+
11
+ def asp_auto_permitted_params(key)
12
+ if sig = self[key][AutoStrongParameters.asp_message_key]
13
+ AutoStrongParameters.verifier.verify(sig) rescue {}
14
+ else
15
+ {}
16
+ end.with_indifferent_access
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,2 @@
1
+ module AutoStrongParameters::ControllerPermitter
2
+ end
@@ -0,0 +1,28 @@
1
+ require 'auto_strong_parameters/auto_permit'
2
+ require 'auto_strong_parameters/auto_form_params'
3
+
4
+ module AutoStrongParameters
5
+ require 'rails/railtie'
6
+
7
+ class Railtie < ::Rails::Railtie
8
+ initializer 'auto_strong_parameters.add_to_rails' do
9
+ ActiveSupport.on_load :action_view do
10
+ AutoStrongParameters::Railtie.apply_form_helpers_patch
11
+ end
12
+
13
+ ActiveSupport.on_load :action_controller do
14
+ AutoStrongParameters::Railtie.apply_auto_permit_patch
15
+ end
16
+ end
17
+ end
18
+
19
+ class Railtie
20
+ def self.apply_form_helpers_patch
21
+ ActionView::Base.send(:include, AutoStrongParameters::AutoFormParams)
22
+ end
23
+
24
+ def self.apply_auto_permit_patch
25
+ ActionController::Parameters.send(:include, AutoStrongParameters::AutoPermit)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module AutoStrongParameters
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
4
+ require 'auto_strong_parameters/railtie'
5
+
6
+ module AutoStrongParameters
7
+ # Rails' message_verifier exists with a stable API in all versions of Rails
8
+ # since 4.2.
9
+ def self.verifier
10
+ @verifier ||=
11
+ ActiveSupport::MessageVerifier.new("auto_strong_parameters", serializer: JSON)
12
+ end
13
+
14
+ # Provide your own custom verifier for AutoStrongParameters. Must respond to
15
+ # #generate which takes an object and returns a string and #verify which
16
+ # takes a string and returns an object.
17
+ def self.verifier=(custom_verifier)
18
+ @verifier = custom_verifier
19
+ end
20
+
21
+ def self.asp_message_key
22
+ @asp_message_key ||= :"_asp_params"
23
+ end
24
+
25
+ def self.asp_message_key=(val)
26
+ @asp_message_key = val
27
+ end
28
+
29
+ def self.to_strong_params_shape(obj)
30
+ items = Set.new
31
+ hsh = {}
32
+
33
+ case obj
34
+ when Hash
35
+ obj.each do |key, val|
36
+ case val
37
+ when Hash
38
+ hsh[key] ||= {}
39
+ hsh[key] = to_strong_params_shape(val)
40
+ when Array
41
+ hsh[key] ||= []
42
+ hsh[key] << to_strong_params_shape(val)
43
+ else
44
+ items << key.to_s
45
+ end
46
+ end
47
+ if hsh.empty?
48
+ items.flatten.to_a
49
+ elsif items.empty?
50
+ hsh
51
+ else
52
+ hsh.transform_values!(&:flatten)
53
+ [*items.flatten, hsh].flatten
54
+ end
55
+
56
+ when Array
57
+ obj.each do |item|
58
+ case item
59
+ when Hash
60
+ items << to_strong_params_shape(item)
61
+ when Array
62
+ items << to_strong_params_shape(item)
63
+ else
64
+ # nothing
65
+ end
66
+ end
67
+
68
+ if hsh.empty?
69
+ items.flatten.to_a
70
+ else
71
+ hsh.transform_values!(&:flatten)
72
+ [*items.flatten, hsh]
73
+ end
74
+
75
+ else
76
+ nil
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,47 @@
1
+ class BasicController < ActionController::Base
2
+ include Rails.application.routes.url_helpers
3
+
4
+ self.view_paths = [ActionView::FixtureResolver.new(
5
+ "basic/new.html.erb" => <<~NEW_USER_FORM
6
+ <%= form_for @user, url: "/auto_permit" do |f| %>
7
+ <%= f.text_field :name %>
8
+ <%= email_field :user, :email %>
9
+ <%= f.text_area :description %>
10
+ <%= f.telephone_field :phone %>
11
+ <%= f.date_field :dob %>
12
+ <%= f.time_field :lunch_time %>
13
+ <%= f.datetime_field :confirmed_at %>
14
+ <%= f.month_field :birth_month %>
15
+ <%= f.week_field :birthday_week %>
16
+ <%= f.url_field :favorite_url %>
17
+ <%= f.number_field :age %>
18
+ <%= f.range_field :years_of_experience %>
19
+ <%= f.password_field :password %>
20
+ <%= f.radio_button :preferred_phone_os, :iphone %>
21
+ <%= f.radio_button :preferred_phone_os, :android %>
22
+ <%= f.fields_for :parents do |parf| %>
23
+ <%= parf.text_field :name %>
24
+ <%= parf.text_area :job %>
25
+ <% end %>
26
+ <%= f.fields_for :pet do |petf| %>
27
+ <%= petf.text_field :nickname %>
28
+ <%= petf.number_field :age %>
29
+ <% end %>
30
+ <% end %>
31
+ NEW_USER_FORM
32
+ )]
33
+
34
+ def new
35
+ @user = User.new
36
+ end
37
+
38
+ def auto_permit
39
+ u = params.auto_permit!(:user)
40
+ render json: u
41
+ end
42
+
43
+ def unpermitted
44
+ u = params.require(:user).permit(:name, pets: [:kind])
45
+ render json: u
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ require_relative './user'
2
+ require_relative './pet'
3
+ require_relative './parent'
@@ -0,0 +1,5 @@
1
+ class Parent
2
+ include ActiveModel::Model
3
+
4
+ attr_accessor :name, :job
5
+ end
data/test/apps/pet.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Pet
2
+ include ActiveModel::Model
3
+
4
+ attr_accessor :nickname, :age
5
+ end
@@ -0,0 +1,57 @@
1
+ require "rails"
2
+
3
+ [
4
+ #'active_record',
5
+ 'active_model',
6
+ 'action_controller',
7
+ 'action_view',
8
+ #'action_mailer',
9
+ #'active_job',
10
+ 'rails/test_unit',
11
+ #'sprockets',
12
+ ].each do |framework|
13
+ begin
14
+ require "#{framework}/railtie"
15
+ rescue LoadError
16
+ end
17
+ end
18
+
19
+ require 'action_view/testing/resolvers'
20
+ require 'rails/test_help'
21
+
22
+ require 'auto_strong_parameters'
23
+
24
+ require_relative './test_app'
25
+
26
+ module Rails42
27
+ class Application < Rails::Application
28
+ config.root = File.expand_path("../../..", __FILE__)
29
+ config.cache_classes = true
30
+
31
+ config.eager_load = false
32
+ config.serve_static_files = true
33
+ config.static_cache_control = "public, max-age=3600"
34
+
35
+ config.consider_all_requests_local = true
36
+ config.action_controller.perform_caching = false
37
+
38
+ config.action_dispatch.show_exceptions = false
39
+
40
+ config.action_controller.allow_forgery_protection = false
41
+
42
+ config.active_support.deprecation = :stderr
43
+
44
+ config.active_support.test_order = :sorted
45
+
46
+ config.middleware.delete "Rack::Lock"
47
+ config.middleware.delete "ActionDispatch::Flash"
48
+ config.middleware.delete "ActionDispatch::BestStandardsSupport"
49
+ config.secret_key_base = TestApp.secret_key_base
50
+ routes.append(&TestApp.routes)
51
+ end
52
+ end
53
+
54
+ require_relative './models'
55
+ require_relative './basic_controller'
56
+
57
+ Rails42::Application.initialize!
@@ -0,0 +1,57 @@
1
+ require "rails"
2
+
3
+ [
4
+ #'active_record',
5
+ 'active_model',
6
+ 'action_controller',
7
+ 'action_view',
8
+ #'action_mailer',
9
+ #'active_job',
10
+ 'rails/test_unit',
11
+ #'sprockets',
12
+ ].each do |framework|
13
+ begin
14
+ require "#{framework}/railtie"
15
+ rescue LoadError
16
+ end
17
+ end
18
+
19
+ require 'action_view/testing/resolvers'
20
+ require 'rails/test_help'
21
+
22
+ require 'auto_strong_parameters'
23
+
24
+ require_relative './test_app'
25
+
26
+ module Rails52
27
+ class Application < Rails::Application
28
+ config.root = File.expand_path("../../..", __FILE__)
29
+ config.cache_classes = true
30
+
31
+ config.eager_load = false
32
+ config.serve_static_files = true
33
+ config.static_cache_control = "public, max-age=3600"
34
+
35
+ config.consider_all_requests_local = true
36
+ config.action_controller.perform_caching = false
37
+
38
+ config.action_dispatch.show_exceptions = false
39
+
40
+ config.action_controller.allow_forgery_protection = false
41
+
42
+ config.active_support.deprecation = :stderr
43
+
44
+ config.active_support.test_order = :sorted
45
+
46
+ config.middleware.delete "Rack::Lock"
47
+ config.middleware.delete "ActionDispatch::Flash"
48
+ config.middleware.delete "ActionDispatch::BestStandardsSupport"
49
+ config.secret_key_base = TestApp.secret_key_base
50
+ routes.append(&TestApp.routes)
51
+ end
52
+ end
53
+
54
+ require_relative './models'
55
+ require_relative './basic_controller'
56
+
57
+ Rails52::Application.initialize!
@@ -0,0 +1,57 @@
1
+ require "rails"
2
+
3
+ [
4
+ #'active_record',
5
+ 'active_model',
6
+ 'action_controller',
7
+ 'action_view',
8
+ #'action_mailer',
9
+ #'active_job',
10
+ 'rails/test_unit',
11
+ #'sprockets',
12
+ ].each do |framework|
13
+ begin
14
+ require "#{framework}/railtie"
15
+ rescue LoadError
16
+ end
17
+ end
18
+
19
+ require 'action_view/testing/resolvers'
20
+ require 'rails/test_help'
21
+
22
+ require 'auto_strong_parameters'
23
+
24
+ require_relative './test_app'
25
+
26
+ module Rails60
27
+ class Application < Rails::Application
28
+ config.root = File.expand_path("../../..", __FILE__)
29
+ config.cache_classes = true
30
+
31
+ config.eager_load = false
32
+ config.serve_static_files = true
33
+ config.static_cache_control = "public, max-age=3600"
34
+
35
+ config.consider_all_requests_local = true
36
+ config.action_controller.perform_caching = false
37
+
38
+ config.action_dispatch.show_exceptions = false
39
+
40
+ config.action_controller.allow_forgery_protection = false
41
+
42
+ config.active_support.deprecation = :stderr
43
+
44
+ config.active_support.test_order = :sorted
45
+
46
+ config.middleware.delete "Rack::Lock"
47
+ config.middleware.delete "ActionDispatch::Flash"
48
+ config.middleware.delete "ActionDispatch::BestStandardsSupport"
49
+ config.secret_key_base = TestApp.secret_key_base
50
+ routes.append(&TestApp.routes)
51
+ end
52
+ end
53
+
54
+ require_relative './models'
55
+ require_relative './basic_controller'
56
+
57
+ Rails60::Application.initialize!
@@ -0,0 +1,57 @@
1
+ require "rails"
2
+
3
+ [
4
+ #'active_record',
5
+ 'active_model',
6
+ 'action_controller',
7
+ 'action_view',
8
+ #'action_mailer',
9
+ #'active_job',
10
+ 'rails/test_unit',
11
+ #'sprockets',
12
+ ].each do |framework|
13
+ begin
14
+ require "#{framework}/railtie"
15
+ rescue LoadError
16
+ end
17
+ end
18
+
19
+ require 'action_view/testing/resolvers'
20
+ require 'rails/test_help'
21
+
22
+ require 'auto_strong_parameters'
23
+
24
+ require_relative './test_app'
25
+
26
+ module Rails61
27
+ class Application < Rails::Application
28
+ config.root = File.expand_path("../../..", __FILE__)
29
+ config.cache_classes = true
30
+
31
+ config.eager_load = false
32
+ config.serve_static_files = true
33
+ config.static_cache_control = "public, max-age=3600"
34
+
35
+ config.consider_all_requests_local = true
36
+ config.action_controller.perform_caching = false
37
+
38
+ config.action_dispatch.show_exceptions = false
39
+
40
+ config.action_controller.allow_forgery_protection = false
41
+
42
+ config.active_support.deprecation = :stderr
43
+
44
+ config.active_support.test_order = :sorted
45
+
46
+ config.middleware.delete "Rack::Lock"
47
+ config.middleware.delete "ActionDispatch::Flash"
48
+ config.middleware.delete "ActionDispatch::BestStandardsSupport"
49
+ config.secret_key_base = TestApp.secret_key_base
50
+ routes.append(&TestApp.routes)
51
+ end
52
+ end
53
+
54
+ require_relative './models'
55
+ require_relative './basic_controller'
56
+
57
+ Rails61::Application.initialize!
@@ -0,0 +1,56 @@
1
+ require "rails"
2
+
3
+ [
4
+ #'active_record',
5
+ 'active_model',
6
+ 'action_controller',
7
+ 'action_view',
8
+ #'action_mailer',
9
+ #'active_job',
10
+ 'rails/test_unit',
11
+ #'sprockets',
12
+ ].each do |framework|
13
+ begin
14
+ require "#{framework}/railtie"
15
+ rescue LoadError
16
+ end
17
+ end
18
+
19
+ require 'action_view/testing/resolvers'
20
+ require 'rails/test_help'
21
+
22
+ require 'auto_strong_parameters'
23
+
24
+ require_relative './test_app'
25
+
26
+ module Rails70
27
+ class Application < Rails::Application
28
+ config.root = File.expand_path("../../..", __FILE__)
29
+ config.cache_classes = true
30
+
31
+ config.eager_load = false
32
+ config.serve_static_files = true
33
+ config.static_cache_control = "public, max-age=3600"
34
+
35
+ config.consider_all_requests_local = true
36
+ config.action_controller.perform_caching = false
37
+
38
+ config.action_dispatch.show_exceptions = false
39
+
40
+ config.action_controller.allow_forgery_protection = false
41
+
42
+ config.active_support.deprecation = :stderr
43
+
44
+ config.active_support.test_order = :sorted
45
+
46
+ config.middleware.delete Rack::Lock
47
+ config.middleware.delete ActionDispatch::Flash
48
+ config.secret_key_base = TestApp.secret_key_base
49
+ routes.append(&TestApp.routes)
50
+ end
51
+ end
52
+
53
+ require_relative './models'
54
+ require_relative './basic_controller'
55
+
56
+ Rails70::Application.initialize!
@@ -0,0 +1,7 @@
1
+ def routes_block
2
+ -> do
3
+ get "new" => "basic#new"
4
+ post "auto_permit" => "basic#auto_permit"
5
+ post "unpermitted" => "basic#unpermitted"
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ class TestApp
2
+ def self.routes
3
+ -> do
4
+ get "new" => "basic#new"
5
+ post "auto_permit" => "basic#auto_permit"
6
+ post "unpermitted" => "basic#unpermitted"
7
+ end
8
+ end
9
+
10
+ def self.secret_key_base
11
+ '49837489qkuweoiuoqwehisuakshdjksadhaisdy78o34y138974xyqp9rmye8yrpiokeuioqwzyoiuxftoyqiuxrhm3iou1hrzmjk'
12
+ end
13
+ end
data/test/apps/user.rb ADDED
@@ -0,0 +1,23 @@
1
+ class User
2
+ include ActiveModel::Model
3
+
4
+ attr_accessor :name, :email, :description, :phone, :dob, :lunch_time,
5
+ :confirmed_at, :birth_month, :birthday_week, :favorite_url, :age,
6
+ :years_of_experience, :password, :preferred_phone_os
7
+
8
+ def parents
9
+ @parents ||= [Parent.new]
10
+ end
11
+
12
+ def parents_attributes=(val)
13
+ @parents = Array.wrap(val)
14
+ end
15
+
16
+ def pet
17
+ @pet ||= Pet.new
18
+ end
19
+
20
+ def pet_attributes=(val)
21
+ @pet = val
22
+ end
23
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class AutoFormParamsTest < ActionController::TestCase
6
+ setup do
7
+ @controller = BasicController.new
8
+ end
9
+
10
+ def signature
11
+ AutoStrongParameters.verifier.generate(permitted_keys)
12
+ end
13
+
14
+ def permitted_keys
15
+ {
16
+ "user" => [
17
+ "name",
18
+ "email",
19
+ "description",
20
+ "phone",
21
+ "dob",
22
+ "lunch_time",
23
+ "confirmed_at",
24
+ "birth_month",
25
+ "birthday_week",
26
+ "favorite_url",
27
+ "age",
28
+ "years_of_experience",
29
+ "password",
30
+ "preferred_phone_os",
31
+ {
32
+ "parents_attributes"=>[
33
+ "name",
34
+ "job",
35
+ ],
36
+ "pet_attributes"=>[
37
+ "nickname",
38
+ "age",
39
+ ],
40
+ },
41
+ ],
42
+ }
43
+ end
44
+
45
+ def test_new
46
+ get :new
47
+ assert_response :ok
48
+
49
+ assert_select "form[id='new_user']"
50
+ assert_select "form[id='new_user'] input[name='#{AutoStrongParameters.asp_message_key}']" do
51
+ assert_select "[value=?]", signature
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class AutoPermitTest < ActionController::TestCase
6
+ setup do
7
+ @controller = BasicController.new
8
+ end
9
+
10
+ def user_params
11
+ {
12
+ name: 'John',
13
+ age: '30',
14
+ pets: [
15
+ { name: "Fluffy", kind: "dog" }
16
+ ],
17
+ }
18
+ end
19
+
20
+ def signature
21
+ AutoStrongParameters.verifier.generate(permitted_keys)
22
+ end
23
+
24
+ def message_key
25
+ AutoStrongParameters.asp_message_key
26
+ end
27
+
28
+ def permitted_keys
29
+ { "user" => ['name', 'age', { 'pets' => ['name', 'kind'] }] }
30
+ end
31
+
32
+ # Rails 4.2 does not have the keyword API for #process et al.
33
+ def process_args(args)
34
+ if defined? Rails42
35
+ args
36
+ else
37
+ { params: args }
38
+ end
39
+ end
40
+
41
+ def test_unpermitted
42
+ post :unpermitted, **process_args(user: user_params)
43
+ assert_response :ok
44
+ j = ActiveSupport::JSON.decode(response.body)
45
+
46
+ assert_equal 'John', j['name']
47
+ assert_nil j['age']
48
+ assert_nil j['pets'][0]['name']
49
+ assert_equal 'dog', j['pets'][0]['kind']
50
+ end
51
+
52
+ def test_auto_permit
53
+ post :auto_permit, **process_args(user: user_params.merge(message_key => signature))
54
+ assert_response :ok
55
+ j = ActiveSupport::JSON.decode(response.body)
56
+
57
+ assert_equal 'John', j['name']
58
+ assert_equal '30', j['age']
59
+ assert_equal 'dog', j['pets'][0]['kind']
60
+ assert_equal 'Fluffy', j['pets'][0]['name']
61
+ end
62
+
63
+ def test_auto_permit_incorrect_signature
64
+ post :auto_permit, **process_args(user: user_params.merge(message_key => 'abc123'))
65
+ assert_response :ok
66
+ j = ActiveSupport::JSON.decode(response.body)
67
+
68
+ assert_nil j['name']
69
+ assert_nil j['age']
70
+ end
71
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class AutoStrongParametersTest < Minitest::Test
6
+ def to_strong_params_shape(h)
7
+ AutoStrongParameters.to_strong_params_shape(h)
8
+ end
9
+
10
+ def test_to_strong_params_shape
11
+ assert_equal ["name"], to_strong_params_shape({"name" => "Steve"})
12
+ assert_equal ["name", "age"], to_strong_params_shape({"name" => "Steve", age: 5})
13
+ assert_equal ["name", {"pet" => ["name"]}], to_strong_params_shape({"name" => "Steve", "pet" => { "name" => "Fluffy" }})
14
+ assert_equal ["name", {"pet" => ["name"]}], to_strong_params_shape({"name" => "Steve", "pet" => { "name" => "Fluffy" }})
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'pry'
4
+
5
+ ENV["RAILS_ENV"] = "test"
6
+ ENV['DATABASE_URL'] = 'sqlite3://localhost/:memory:'
7
+
8
+ require 'rails'
9
+
10
+ case Rails.version.slice(0, 3)
11
+ when "4.2"
12
+ require "apps/rails42"
13
+ when "5.2"
14
+ require "apps/rails52"
15
+ when "6.0"
16
+ require "apps/rails60"
17
+ when "6.1"
18
+ require "apps/rails61"
19
+ when "7.0"
20
+ require "apps/rails70"
21
+ else
22
+ raise "Un-tested version of Rails: #{Rails.version}"
23
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: auto_strong_parameters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Drew Ulmer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-08-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: appraisal
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email: drew@unabridgedsoftware.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - README.md
90
+ - Rakefile
91
+ - lib/auto_strong_parameters.rb
92
+ - lib/auto_strong_parameters/auto_form_params.rb
93
+ - lib/auto_strong_parameters/auto_permit.rb
94
+ - lib/auto_strong_parameters/controller_permitter.rb
95
+ - lib/auto_strong_parameters/railtie.rb
96
+ - lib/auto_strong_parameters/version.rb
97
+ - test/apps/basic_controller.rb
98
+ - test/apps/models.rb
99
+ - test/apps/parent.rb
100
+ - test/apps/pet.rb
101
+ - test/apps/rails42.rb
102
+ - test/apps/rails52.rb
103
+ - test/apps/rails60.rb
104
+ - test/apps/rails61.rb
105
+ - test/apps/rails70.rb
106
+ - test/apps/routes.rb
107
+ - test/apps/test_app.rb
108
+ - test/apps/user.rb
109
+ - test/auto_form_params_test.rb
110
+ - test/auto_permit_test.rb
111
+ - test/auto_strong_parameters_test.rb
112
+ - test/test_helper.rb
113
+ homepage: https://github.com/unabridged/auto_strong_parameters
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubygems_version: 3.1.6
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Automatic require and permit of Strong Paramters for your Rails forms.
136
+ test_files:
137
+ - test/auto_form_params_test.rb
138
+ - test/test_helper.rb
139
+ - test/apps/routes.rb
140
+ - test/apps/test_app.rb
141
+ - test/apps/rails52.rb
142
+ - test/apps/rails42.rb
143
+ - test/apps/basic_controller.rb
144
+ - test/apps/parent.rb
145
+ - test/apps/pet.rb
146
+ - test/apps/rails61.rb
147
+ - test/apps/models.rb
148
+ - test/apps/rails60.rb
149
+ - test/apps/rails70.rb
150
+ - test/apps/user.rb
151
+ - test/auto_strong_parameters_test.rb
152
+ - test/auto_permit_test.rb