-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial idea to add permission based whitelisting to params #219
Conversation
…to the new StrongParameters built for Rails, currently only handles the most simple path, to serve as a start for a discussion on whether this is desired, and how it could be incorporated. The deep merging of params causes a problem, it would likely be necessary for a full solution to automatically filter permit params coming from rack
|
||
class PermissionValidator < Validator | ||
|
||
def permissions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think this method is used or necessary?
Thanks for the comments Adam. I want to re-iterate though that its not an attempt to provide a fully specced and working feature yet, just demo how it could be done, and get a discussion on whether this is desired in Grape, and if so, how should things like the params merging be handled. |
Ok, not seeing any interest in discussing this feature. I'll give it a few more days, and if no-one wants it I'll just close. |
We already have a class API < Grape::API
only_allow_the_params_i_declared # needs a better name
end or class API < Grape::API
params do
only_allow_the_params_i_declared # needs a better name
requires ...
end
post foo
end
end |
Giving this another 2 minutes of thought :) - the |
I feel like this should be baked into declared params. If I declare a param, then I'm automatically starting a white list. I can then say |
I am with @mbleigh on this one. |
I'm thinking of implementing a helper called |
I like the idea of including it into the existing helper, since you already have similar :requires functionality of the rails/strong_parameters gem there. Also +1 on the better accessibility of the params hash. We've found the existing params hash occasionally difficult to use due to the middleware params that get merged into it. Would it be easy to make it optionally available as you mentioned, but not specifically because of declared_params, but more wrapped in something addressed to the endpoint? Also, does it actually need a second helper, or could you just wrap the params addressed to the endpoint in a key based on the endpoint name? Not sure if that idea would break backwards compatibility for people, but considering the current params hash I dont think people tend to throw the entire thing at a Object.create call. eg. rails does this
so something like
|
I think there's a lot of good stuff in this thread. Looking forward to an update here from @wyaeld with something clearly explaining in the README that params create a white list (are a reliable way to avoid the |
I definitely like the direction we're going here. I think that
I actually think I like option 3 the best, what are all of your thoughts? |
preference for 2, but any of the options look simple and easy enough to use. When you say cleaning of non-declared params, do you mean the rack related stuff? I'd expect that if you try to send a param not on the whitelist it errors. |
I feel like its slightly user-hostile to throw errors if they supply non-valid params. Just ignore the params seems like the sane solution in such cases. |
Depends whether you are trying to implement the attr_accessible functionality of rails, or the new strong_params coming in rails4. For the record I was using the latter as inspiration, since attr_accessible is already completely available us. |
Wanted to chime in. I like errors. I find it much harder to figure out what went wrong when a system completely ignores what you've done. I'm currently white listing some params via helpers and throwing errors, so I might be bias. |
I'm not really interested in implementing anyone else's system blindly...I don't see what the advantage is to throwing errors over ignoring. It's not the same as A middle ground could be to keep a hash of undeclared params as well. Then to error on whitelisting you could do something like: before do
error! "invalid params: #{params[:undeclared].keys.join(', ')}", 400 if params[:undeclared].any?
end |
Agreed, thats why I kept the initial pull to the minimal to get the idea across, rather than a full implementation. I like your error being thrown there, I'm fine with adding 1 line of code to make that the behaviour I want rif you prefer it not be default. declared/undeclared seems less clear naming. The line of code is obviously declaring something, but I'd prefer valid or permits or something that directly expresses the idea of only allowing 'these' params through |
Preference for option 3, declared(params). Bad idea to pollute the params hash more than absolutely necessary IMO. Also provides more flexibility (options for enhancements) in the future I think. |
If a whitelist system is implemented I think allowing the users to chose whether they want to raise an error or ignore is a wise decision, I prefer an error to be raised but I agree different applications may have different needs, I just hate when a method allows me to put anything in its options hash and just ignore the invalid keys (activerecord is a perfect example of this and gave me a lot of headaches). I like option 3, for my current use cases I don't send blindly my hash to anything like activerecord so if more keys are present they will just be ignored. Whitelisting with nested parameter should be fun to implement if we can ever come to an agreement on what is the expected behavior. |
Ok, so we know that this specific pull is not going to make it. I am going to close it, please yell at me if you think otherwise. We do want an easy, documented way for users to have |
This solves at least part of the problem described by #219 by giving a simple helper that can be used at the endpoint level to use only declared parameters. Basic usage: class MyAPI < Grape::API params do requires :name optional :email end post :users do # POST /users # name=Some+Name # This will only have :name and :email keys declared(params) # This will only have "name" and "email" keys declared(params, stringify: true) # This will only have a :name param declared(params) end end
This pull isn't really intended to be merged as-is, but more as a convenient way to start a dialogue around the concept. It does work and included tests.
This is conceptually similar to the new StrongParameters built for Rails, in this case for each endpoint you can add a list of parameters to the Endpoint via permit(:foo, :bar, :baz) that will deny anyone calling that endpoint with params not on the whitelist.
This initial example only handles the most simple path. The deep merging of params causes a problem, it would likely be necessary for a full solution to automatically filter permit params coming from rack. Currently I used a simple hack of passing an alternative params hash to this particular validator.
I personally agree with the emerging trend that parameter whitelisting is a concern for the controller/api layer, and you should have the flexibility to permit based on the particular action that is occuring, rather than just declaring accessible in the models. In complex applications that isn't always sufficient, especially if different endpoints in the API serve different levels of authorisation.
What do other people think?