Skip to content
This repository has been archived by the owner on Aug 17, 2017. It is now read-only.

Feature proposal - ActionController::Parameters#allow / ActionController::Parameters#forbid - Allowed parameter values #252

Closed
msimonborg opened this issue Aug 1, 2017 · 2 comments

Comments

@msimonborg
Copy link

msimonborg commented Aug 1, 2017

Proposal

A method that lets you restrict the allowed values for a given set of permitted params. If the value is not in the allowed list then the param will not make it into the strong params. Alternatively or in addition, an inverse method that only permits the param if the value is NOT in a forbidden list

API

#allow

params.require(:user).permit(:id, :role).allow(role: 'employee') # role is only permitted if the value is 'employee'

or

params.require(:user).permit(:id, :role).allow(role: ['employee', 'guest']) # also works with an array of values

#forbid

params.require(:user).permit(:id, :role).forbid(role: 'admin') # role is only permitted if the value is NOT 'employee'

params.require(:user).permit(:id, :role).forbid(role: ['admin', 'owner']) # also works with an array of values

Implementation

I think it's fairly lightweight and simple to implement. Without putting it through rigorous testing, something like below might work

class ActionController::Parameters
  def allow(filters = {})
    filters.each do |filter_key, filter_val|
      delete_if do |params_key, params_val|
        filter_key.to_s == params_key && !Array(filter_val).include?(params_val)
      end
    end
    self
  end

  def forbid(filters = {})
    filters.each do |filter_key, filter_val|
      delete_if do |params_key, params_val|
        filter_key.to_s == params_key && Array(filter_val).include?(params_val)
      end
    end
    self
  end
end
@rafaelfranca
Copy link
Member

Thank you for the pull request but this kind of validation is better suited to Active Model validations.

@msimonborg
Copy link
Author

msimonborg commented Aug 1, 2017

The use case is more to filter params at the controller level based on the roles/permissions of the user submitting the request, not to supersede or compete with model validations. An attribute may be valid for the application, but you want to restrict the ability of a user to submit that particular value in mass assignment based on roles.

It comes from this SO question https://stackoverflow.com/questions/45439684/allowing-only-certain-values-though-a-strong-parameter-in-rails-4/45440625#45440625

And it appears it used to be possible and people took advantage of the ability #167 & https://stackoverflow.com/questions/18279229/rails-4-forcing-specific-values-with-strong-parameters

In any case, I wrote a gem for it https://github.com/msimonborg/allowable

I hope you think it's appropriate to reopen the issue, but thanks anyway for considering!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants