Cannot Assign Protected Attributes Massively

My features file is as follows:

 Given there are the following users: | email | password | admin | | admin@ticketee.com | password | true | 

And my user model does not declare the admin attribute as attr_accessible to prevent bulk assignment. Accordingly, I made changes to the user_steps.rb file to solve this problem.

 Given /^there are the following users:$/ do |table| table.hashes.each do |attributes| unconfirmed = attributes.delete("unconfirmed") == "true" @user = User.create!(attributes) @user.update_attribute("admin", attributes["admin"] == "true") @user.confirm! unless unconfirmed end end 

Now it should work according to the book - Rails3 in action. I checked the code on my online repo . Doing this with a cucumber gives the following error:

 Can't mass-assign protected attributes: admin (ActiveModel::MassAssignmentSecurity::Error) ./features/step_definitions/user_steps.rb:4:in `block (2 levels) in <top (required)>' ./features/step_definitions/user_steps.rb:2:in `each' ./features/step_definitions/user_steps.rb:2:in `/^there are the following users:$/' features/creating_projects.feature:7:in `Given there are the following users:' 

Any help would be greatly appreciated. I really cannot understand what is wrong here.

Thanks a lot!

+4
source share
5 answers

In the user model add:

 attr_accessible :admin 

Update:

The admin attribute can be assigned by the mass, and any hacker can easily set it by sending it with parameters.

+8
source

I did it by changing the definition of the step:

  Given /^there are the following users:$/ do |table| table.hashes.each do |attributes| unconfirmed = attributes.delete("unconfirmed") == "true" admin = attributes.delete("admin") == "true" @user = User.create!(attributes) @user.admin = admin @user.confirm! unless unconfirmed end end 
+3
source

Why not just use @user.admin = attributes["admin"] == "true" ?

You will need to get rid of the admin value from the attribute hash, so the full code will be

 admin = attributes.delete("admin") == "true" ... @user = User.new(attributes) @user.admin = admin @user.save! 

I changed User.create! to User.new + @ user.save because you are setting the attribute but not saving the model after. If @ user.confirm! saves the model, you will not see any errors, but it is not a good practice to rely on side effects from other similar methods. Better to be explicit.

+1
source

Assuming this is based on β€œRails 3 in action,” the sample code actually has the same problem. From the magazine:

 WARNING: Can't mass-assign protected attributes: admin (0.1ms) SELECT 1 FROM "users" WHERE "users"."email" = ' sfcarroll2@gmail.com ' LIMIT 1 User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."confirmation_token" = 'f9zDB57RDXsziBdGpmnW' LIMIT 1 

However, the mass_assignment_sanitizer parameter is not set in the config / environment / development.rb file . By default, the new rails 3.2 project will install this. If it is commented out, the code will be executed. The default value is:

 config.active_record.mass_assignment_sanitizer = :strict 

The sample code then sets the attribute using the private set_admin method. Is this a good coding practice? I'm not sure, but it works.

This is a great book, by the way.

+1
source

I think the easiest way to do this is:

 Given /^there are the following users:$/ do |table| table.hashes.each do |attributes| unconfirmed = attributes.delete("unconfirmed") == "true" # this will delete the attribute unconfirmed from first # scenario on the signing_in.feature but it also make a variable unconfirmed true (2 in one action) admin = attributes.delete("admin") == "true" @user = User.create!(attributes) @user.update_attribute("admin", "true") if admin # with the user and password, it will create the user as admin. @user.confirm! unless unconfirmed # this is work for the second scenario check rails 3 in action page 152. end end 

This way you remove the admin attribute from the attributes so that you can create a new user; no bulk attribute error. But for the purpose of "test" we save the administrative variable for assigning the user.admin attribute if the admin was true. The point here is that you cannot make the admin available on the User model to protect your site from hacking, but we do this to pass our test. On your website, you must implement a secure way to update the user after creating it.

0
source

Source: https://habr.com/ru/post/1401879/


All Articles