ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: - ruby-on-rails-3

I am following along the tutorial Ruby on Rail 3 Essential Training from Lynda.com. I am having a difficult time creating an Active Record Entry. This is the error I get in my console.
1.9.3p125 :007 > user = User.new(:first_name => "Mike", :last_name => "Jones")
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: first_name, last_name
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security.rb:230:in `sanitize_for_mass_assignment'
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.3/lib/active_record/attribute_assignment.rb:75:in `assign_attributes'
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.3/lib/active_record/base.rb:498:in `initialize'
from (irb):7:in `new'
from (irb):7
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.3/lib/rails/commands/console.rb:47:in `start'
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.3/lib/rails/commands/console.rb:8:in `start'
from /home/mark/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.3/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>`
This is what I have in my Model:
class User < ActiveRecord::Base
attr_accessible :first_name, :last_name
end
What am I doing wrong. I have rails 3.2.3

From what I know that lynda course was developed on rails3 and in rails 3.2.3 there is no mass assignment by default. You have to go your model and add attr_accessible :name, :position, :visible. Basically you have to add every attribute you want to mass assign.

Try to restart the console. If you have created the model for user after the console was launched, you should restart it.

Without any precautions Mass-assignment allows attackers to set any database column’s value, hence it has been disabled by default.
def signup
params[:user] # => {:name => “ow3ned”, :admin => true}
#user = User.new(params[:user])
end
The detailed description is in the Ruby On Rails Security Guide.

I just added the attr_accessible :first_name, :last_name, :username line to the models file.
This worked for me.

I was too following along the tutorial Ruby on Rail 3 Essential Training from Lynda.com, if anybody had the same problem here is what worked for me,
Turn off the security setting. Open config/application.rb and change config.active_record.whitelist_attributes to false instead of true. This makes your app a little less secure, but allows you to quickly move forward with the tutorial.
this is from: http://www.lynda.com/Ruby-on-Rails-3-tutorials/essential-training/55960-2/faqs

Make sure to put attr_accessible :first_name, :last_name in the User model and not in the controller.

Related

Devise allow email uniqueness within scope

I'm in the process of upgrading a large project from rails 2 to rails 3, as a part of that upgrade I'm replacing a very old restful_athentication with devise.
The problem I'm having is that in the existing users table emails are validated like this.
validates_uniqueness_of :email, :scope => :account_id # No dupes within account
So if I add the index from the migration to add devise to users it WILL fail.
Is there a way that I can use
add_index :users, [:email,:account_id]
And have devise work properly?
I managed to get this working on my own, I added the following to config/initializer/devise.rb
config.authentication_keys = [ :email , :account_id]

No Mass assignment with attr_accessible set in model Rails 3.2.2

I have am creating a twitter style following relationship between users in my Rails 3.2.2 application. I have User and Relationship models.
class Relationship < ActiveRecord::Base
belongs_to :user
belongs_to :follower, :class_name => 'User'
attr_accessible :follower, :follower_id, :status
end
class User < ActiveRecord::Base
has_many :authentications, class_name: 'UserAuthentication'
has_many :relationships
has_many :followers, :through => :relationships
has_many :following, :through => :relationships, :foreign_key => 'follower_id', :source => :follower
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :omniauthable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
end
I decided to leave the devise and omniauth stuff in there incase it happened to be part of the issue, though I doubt it.
In the command line I am working with two users u1 and u2.
I run the command
u1.followers.build(:follower_id=>u2.id)
and receive this error
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: follower_id
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.2/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.2/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.2/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.2/lib/active_model/mass_assignment_security.rb:228:in `sanitize_for_mass_assignment'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/attribute_assignment.rb:75:in `assign_attributes'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/base.rb:495:in `initialize'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/reflection.rb:183:in `new'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/reflection.rb:183:in `build_association'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/associations/association.rb:233:in `build_record'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/associations/has_many_through_association.rb:91:in `build_record'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/associations/collection_association.rb:112:in `build'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/associations/collection_proxy.rb:46:in `build'
from (irb):29
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.2/lib/rails/commands/console.rb:47:in `start'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.2/lib/rails/commands/console.rb:8:in `start'
from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.2/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
It's the first time I have used the build method on an association but it seems quite convenient if I can get it to work. If you need any more information please ask. Thanks for your help!
The follower_id is a field on Relationship. When you call u1.followers.build you are building a User which doesn't have a follower_id column. Since you are using attr_accessible, rails doesn't let you know that column doesn't exist, it just tells you you don't have access to it. (Which is good form a security perspective.)
Regardless, looks like you want to do:
u1.relationships.build(:follower_id => u2.id)
or maybe
u1.followers << u2
(With the code you showed I'm not 100% sure the second case will work off the type of my head -- you might need to further tweak your attr_accessible to get this second method to work. First one will definitely work, though.)

Undefined method for a belongs_to association

My code:
class User < ActiveRecord::Base
belongs_to :university
end
class University < ActiveRecord::Base
has_many :users, dependent: :destroy
end
and my model User has a university_id attribute.
If I do University.find(1).users I get the list of users, but if I do User.find(1).university (and I checked that university_id is not nil here) I get:
NoMethodError: undefined method `university' for #<User:0x00000003859fc8>
from /home/mari/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.0.10/lib/active_model/attribute_methods.rb :392:in `method_missing'
from /home/mari/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.0.10/lib/active_record/attribute_methods. rb:46:in `method_missing'
from (irb):14
from /home/mari/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.0.10/lib/rails/commands/console.rb:44:in`start'
from /home/mari/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.0.10/lib/rails/commands/console.rb:8:in start'
from /home/mari/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.0.10/lib/rails/commands.rb:23:in
`<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
What am I doing wrong? I have another models and they are working just fine. Any suggestions? Thanks in advance
I still can't comment so I'll burn an answer:
Somehow the belongs_to :university in the User model isn't being recognized. When testing, are you certain that the User model has been saved and is in the right place and that the server or console has been refreshed? Most commonly, in my experience, when I'm meddling with models, I have to refresh my server and console often to get clean results.
Try
User.where("id =?", 1).first.university

Writing spec for devise RegistrationsController that will make sure users can't change their role - cryptic error message

I have a rails 3.1 app using Devise and CanCan to mange users and roles. I want to make sure that users can update their password, but not their roles. (So ordinary users can't give themselves an admin role, basically). I have overridden the Devise class "RegistrationsController" with some code like this:
def update
# this is my attempt to stop people from updating their roles
# and giving themselves "Admin" priveledges.
params.delete("role_ids")
super
end
I'm hoping this will prevent hackers from updating the "role_ids" field in the user to change their priviledges. (If there is a better way to achieve this, please say!) My problem is I can't seem to write a spec that will test that this code works. My spec looks like this:
require 'spec_helper'
describe RegistrationsController do
before (:each) do
#user = Factory(:user)
sign_in #user
end
it "should update the user attributes but not the roles" do
user_params = {"name" => "new_name", "role_ids" => ["2"],}
put :update, { :id => #user.id, :user => user_params}
#user = User.find(#user.id)
#user.name.should == "new_name"
#user.roles.should be_empty
end
end
The trouble is this test doesn't execute. I get an error message like this:
Failures:
1) RegistrationsController should update the user attributes but not the roles
Failure/Error: put :update, { :id => #user.id, :user => user_params}
AbstractController::ActionNotFound:
Could not find devise mapping for path "/user?id=29&user%5Bname%5D=new_name&user%5Brole_ids%5D%5B%5D=2".
Maybe you forgot to wrap your route inside the scope block? For example:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
# ./spec/controllers/registrations_controller_spec.rb:13:in `block (2 levels) in <top (required)>'
I don't understand what the error message is asking me to do. My routes seem fine and my application seems to work otherwise. Can anyone help?
Try this in your setup
#request.env["devise.mapping"] = Devise.mappings[:user]
For details see How To: Controllers and Views tests with Rails 3

model missing required attr_accessor for 'photo_file_name' when uploading with paperclip and S3 on heroku

Setting up paperclip with S3 in my linux dev environment was a snap -- everything works out of the box. However, I can't get it to work on Heroku.
When I try to do an upload, the log shows:
Processing ItemsController#create (for 72.177.97.9 at 2010-08-26 16:35:14) [POST]
Parameters: {"commit"=>"Create", "authenticity_token"=>"0Hy3qvQBHE1gvFVaq32HMy2ZIopelV0BHbrSeHkO1Qw=", "item"=>{"photo"=>#<File:/home/slugs/270862_4aa601b_4b6f/mnt/tmp/RackMultipart20100826-6286-1256pvc-0>, "price"=>"342", "name"=>"a new item", "description"=>"a new item", "sold"=>"0"}}
Paperclip::PaperclipError (Item model missing required attr_accessor for 'photo_file_name'):
I found one blog post that referenced this error, and it said to add this to my model:
attr_accessor :photo_file_name
attr_accessor :photo_content_type
attr_accessor :photo_file_size
attr_accessor :photo_updated_at
That does indeed make the model missing required attr_accessor for 'photo_file_name' error go away, but it still doesn't work. See my other question for details. As I have figured out that with the attr_accessor lines added to my model the uploads fail even on my dev system, I suspect that is not the right answer.
Found the problem: needed to update the database.
heroku run rake:db:migrate
heroku restart
I had done what I thought would have accomplished the same thing already:
heroku rake db:schema:load
but perhaps that doesn't work or something went wrong in the process.
Error like this occurs if you create wrong column type in migration. When you define new table migration for paperclip, you need to specify t.attachment :name insted of t.string :name. Or add_attachment :table, :name when you add new paperclip column in existed table. And now you don't need to add these attributes in attr_accessor in model.
Well, this message seems to be because the columns it's missing. Try create a migration creating the columns:
class AddPhotoToEvent < ActiveRecord::Migration
def change
add_column :events, :photo_file_name, :string
add_column :events, :photo_content_type, :string
add_column :events, :photo_file_size, :integer
add_column :events, :photo_updated_at, :datetime
end
end
This work for me, here i have a table events with photo