0

So, this is a rails app but really more of a general ruby question:

I have a model with several scopes. For example:

Photo.recent
Photo.popular
Photo.featured

I have a "browse photos" view in my app where I want to be able to pass a single param and let the user specify a scope they want to view, ie:

example.com/photos/browse?view=recent

This gives me params[:view], and I need to attach that as a method call on Photo.

So my first question is, how can you do that kind of thing in Ruby?

Second, this could be a security risk if I can't constrain the input, if I just attach Photo.whatever the user types in the url then I'm at risk for a hacker saying example.com/photos/browse?view=delete_all That, obviously, is a bad idea.

So my second question is, how can I create a whitelist or something for what can be called -- or even better setup some kind of method that can accept the param from the URL safely and only return information if the user is requesting a valid named scope.

Lastly, I have some scopes that are only for admins. I have user abilities defined (using CanCan) so I can query current_user.has_role? to check if a user is authorized for anything, but is there a way to associate permissions with a scope?

Thanks!

2 Answers 2

2

TBH, unless you have a lot of these scopes, I would just hardcode them or create a hash mapping the url param values to lambdas

In the event that you do want to do exactly what you said, you could do something like:

whitelist = %w(
  recent
  popular
  featured
)

if whitelist.include? params[:view]
  photos = Photo.send params[:view].to_sym
end

See: http://apidock.com/ruby/Object/send

EDIT: Perhaps try this?

if Photo.valid_scope_name? params[:view]
  photos = Photo.send params[:view].to_sym
end

It's a protected method, so you might have to use:

if Photo.send :valid_scope_name?, params[:view]
  photos = Photo.send params[:view].to_sym
end

http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/valid_scope_name%3F

Sign up to request clarification or add additional context in comments.

1 Comment

This looks workable, and I think the number of scopes is manageable. Out of curiosity do you have any idea how to do it without a manually-written whitelist?
1

To send a method, use the send method :)

Photo.send(params[:view].to_sym)

However, you are 100% correct to assume this (might) be a security concern. Subsequently, you may want to do something like the following:

Photo.send(params[:view].to_sym) if %w(recent popular featured).include?(params[:view])

1 Comment

FYI the send method accepts strings too... no need for to_sym

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.