Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 Strong Parameters : can I 'exclude' / blacklist attributes instead of permit / whitelist?

I'm migrating a Rails 3 app to Rails 4 and I'm in the process of converting attr_accessible properties to strong parameters in the controller. The API Documentation shows how to 'permit' attributes:

def person_params
  params.require(:person).permit(:name, :age)
end

However the vast majority of my attributes are mass-assignment safe. It's only a few attributes like :account_id and :is_admin that I need to blacklist.

Is it possible to blacklist attributes instead of whitelisting almost every attribute? E.g something like:

def user_params
  params.require(:user).exclude(:account_id, :is_admin)
end
like image 581
Pete Avatar asked Sep 17 '13 08:09

Pete


4 Answers

I think you shouldn't really do that for reasons outlined by @Damien, but heres a solution I just found.

params.require(:user).except!(:account_id, :is_admin).permit!

This will remove :account_id, :is_admin from hash and permit all other parameters. But again - this is potentially insecure.

Why this works? Because ActionController::Parameters inherits from Hash!

Update 4th July 2016

In Rails 5 this probably doesn't work anymore as per upgrade guide

ActionController::Parameters No Longer Inherits from HashWithIndifferentAccess

like image 133
Mike Szyndel Avatar answered Nov 09 '22 11:11

Mike Szyndel


Whitelisting is more secure.

But u can try: In model:

self.permitted_params
  attribute_names - ["is_admin"]
end

In Controller:

def user_params
  params.require(:user).permit(*User.permitted_params)
end
like image 35
Oleg Haidul Avatar answered Nov 09 '22 11:11

Oleg Haidul


No, this is not possible.
Blacklisting attributes would be a security issue, since your codebase can evolve, and other attributes, which should be blacklisted can be forgotten in the future.

Adding all your whitelisted attributes might seem like a complicated thing when implementing it.
However, it's the only way of keeping your application secure and avoiding disturbing things.

like image 4
Damien MATHIEU Avatar answered Nov 09 '22 12:11

Damien MATHIEU


From the docs: yes, you can, with except, which "returns a new ActionController::Parameters instance that filters out the given keys":

params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
params.except(:a, :b) # => <ActionController::Parameters {"c"=>3} permitted: false>
params.except(:d)     # => <ActionController::Parameters {"a"=>1, "b"=>2, "c"=>3} permitted: false>
like image 2
snowangel Avatar answered Nov 09 '22 10:11

snowangel