"Mass-assigning protected attributes in Rails"

Rails has a great feature called protected attributes which you can set like this:



class User < ActiveRecord:Base
  attr_protected :account_id
end


Or you can use the inverted versions (which I prefer) where you set which attributes are accessible, like this:



attr_accessible :name, :email


What this does is that it tells Rails which attributes can be used in mass-assignment like this:



User.create(:name => "Piyush", :email => "mba.piyushgupta@gmail.com")


or what’s used more:



User.create(params[:user])


Then some malicious hacker cannot use mass-assignment to manually set the account_id.


If you try to assign to protected attributes you’ll get the following warning:



WARNING: Can't mass-assign these protected attributes: account_id


But the problem is: What if I’m no hacker, but I should have unlimited access, for example as an administrator? Then I can’t mass-assign to any protected attributes. Then I’d need to do something like this:



u = User.new(params[:user])
u.account_id = params[:user][:account_id]


Not very pretty.


What I’ve done is that I’ve created an extension to some of the methods taking mass-assignment and added an optional parameter calledguard_protected_attributes which has a default value of true.


Example:



# config/initializers/unprotected_attributes.rb
class ActiveRecord::Base
  def update_attributes_with_unprotected(attributes, guard_protected_attributes = true)
    send :attributes=, attributes, guard_protected_attributes
    save
  end
  alias_method_chain :update_attributes, :unprotected
end


We can do this because the native ActiveRecord::Base#attributes= can also be called with guard_unprotected_attributes.


Now you can call update_attributes like this:



user = User.find(3)
user.update_attributes(params[:user], false)


and it will also assign the protected attributes.


I have made extensions to create, new, update_attributes, andupdate_attributes!.


The ugly part, however, is that to make it work, I had to copy the functions in their entirety which could potentially mean that if you use it on a Rails version other than exactly 2.3.8 it might not work. Sorry for that.

Advertisements
"Mass-assigning protected attributes in Rails"

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s