One controller serving two routes

23 views
Skip to first unread message

John Bachir

unread,
Jul 17, 2012, 1:07:03 PM7/17/12
to declarative_...@googlegroups.com
I have one controller that manages the same polymorphically-related objects for two routes. So imagine comments that can be owned by either a Post or a Photo

/posts/123/comments
/photos/123/comments

Is there a way to do this with filter_resource_access? Essentially two filter_resource_access declarations that "know" which context they are in?

Thanks!
John

Edward Rudd

unread,
Jul 17, 2012, 1:18:42 PM7/17/12
to declarative_...@googlegroups.com
Yes there is...   I have this setup in an application I'm finishing right now..  The source isn't public yet but will be soon, so I'll paste the except here of how I have it configured.

class CommentsController < ApplicationController
   filter_resource_access :nested_in => :commentable

# all actions
protected
  def load_commentable
    @commentable = find_polymorphic
  end

  # I'm overriding this as I'm pre-setting the author for all created comments
  def new_comment_from_params 
    @comment = @commentable.comments.build (params[:comment] || {}).merge(:author => current_user)
  end

private
  # this could probably go on application controller as it's reusable across all polymorphic controllers
  def find_polymorphic 
    params.each do |name, value|
      if name.ends_with?("_id")
        return name[0..-4].classify.constantize.find(value)
      end
    end
    nil
  end
end


--
You received this message because you are subscribed to the Google Groups "declarative_authorization" group.
To view this discussion on the web visit https://groups.google.com/d/msg/declarative_authorization/-/BJe3zEBcn7AJ.
To post to this group, send email to declarative_...@googlegroups.com.
To unsubscribe from this group, send email to declarative_author...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/declarative_authorization?hl=en.

Edward Rudd
OutOfOrder.cc
Skype: outoforder_cc






John Joseph Bachir

unread,
Jul 17, 2012, 2:44:22 PM7/17/12
to declarative_...@googlegroups.com
Great, thank you!

What do your routes look like?

Edward Rudd

unread,
Jul 17, 2012, 2:53:42 PM7/17/12
to John Joseph Bachir, declarative_...@googlegroups.com
On Jul 17, 2012, at 14:44 , John Joseph Bachir wrote:

Great, thank you!

What do your routes look like?

Just your standard nested resource

resources :projects do
resources :comments
end

resources :issues do
resources :comments

John Bachir

unread,
Jul 17, 2012, 2:54:21 PM7/17/12
to declarative_...@googlegroups.com
your load_polymorphic is interesting -- I wonder if some aspect of it could be made part of DA.

I'm also thinking, maybe it's solving the problem at the wrong level... maybe the Rails routing api could be used to access that state. (just thinking out loud, haven't explored it)

John Bachir

unread,
Jul 17, 2012, 2:59:51 PM7/17/12
to declarative_...@googlegroups.com
load_polymorphic might be a security vulnerability. someone can send anything in the GET param that is a class name in the system and you would invoke .find on it. For most things this might be harmless, but the fact that a user can do this on an arbitrary class if of concern.

to be secure it would have to somehow limit the classes to those represented in the routes (/foo/:photo/...)

John Bachir

unread,
Jul 17, 2012, 3:03:27 PM7/17/12
to declarative_...@googlegroups.com
did you leave out the invocation of load_commentable or is it something that is magically invoked by DA (or something else)?

Edward Rudd

unread,
Jul 17, 2012, 3:13:29 PM7/17/12
to John Bachir, declarative_...@googlegroups.com
(combining several of your emails)


On Jul 17, 2012, at 15:03 , John Bachir wrote:

> did you leave out the invocation of load_commentable or is it something that is magically invoked by DA (or something else)?

That is decl_auth magic. look at the in_controller.rb file it looks for several functions to allow you to customize the before filters

> your load_polymorphic is interesting -- I wonder if some aspect of it could be made part of DA.
>
> I'm also thinking, maybe it's solving the problem at the wrong level... maybe the Rails routing api could be used to access that state. (just thinking out loud, haven't explored it)

It was something inspired from a railscast, but does have some issues.. Especially that it doesn't handle more than one level of nesting. I have a revamped one that *should* work better. I could probably figure out how to poke into the rails routing api to figure out what is "expected", but I haven't spent time yet to figure out if it's possible. And yeah.. ideally it would be nice if a secure clean implementation could be baked into Decl_auth.. (:nested_in => :commentable, :polymorphic => true) or something like that.

> load_polymorphic might be a security vulnerability. someone can send anything in the GET param that is a class name in the system and you would invoke .find on it. For most things this might be harmless, but the fact that a user can do this on an arbitrary class if of concern.
>
> to be secure it would have to somehow limit the classes to those represented in the routes (/foo/:photo/...)

I agree that it does have issues.. Though theoretically the routing API should handle that scenario to some extent and just fail to match a route. (not tested though).

anyways, I have a new revamped implementation here.

def load_commentable
@commentable = find_polymorphic [:project, :issue]
end

def find_polymorphic(allowed = [])
params.each do |name, value|
if name.ends_with?("_id")
klass = name[0..-4]
if allowed.blank? || allowed.include?(klass.to_sym)
return klass.classify.constantize.find(value)
else
return nil
end
end
end
nil
end

John Bachir

unread,
Jul 17, 2012, 5:18:00 PM7/17/12
to declarative_...@googlegroups.com, John Bachir
Thanks Edward, very helpful stuff.

Next thought: should the authorization rules reference Project and Issues like normal, or commentable via a scope?

Edward Rudd

unread,
Jul 17, 2012, 5:43:51 PM7/17/12
to declarative_...@googlegroups.com, John Bachir
On Jul 17, 2012, at 17:18 , John Bachir wrote:

Thanks Edward, very helpful stuff.

Next thought: should the authorization rules reference Project and Issues like normal, or commentable via a scope?

How I have things defined is like this

has_permission_on :comments, :to => [:read] do
  if_permitted_to :read, :commentable
end
has_permission_on :comments, :to => [:create,:update, :delete], :join_by => :and do
  if_permitted_to :read, :commentable
  if_attribute :author => is { user }
end

where that blows up is if you try doing something like this.

@issue.comments.with_permissions_to :read

Or even

Comment.with_permissions_to :read

the model scope doesn't understand polymorphic associations at all correctly...  theoretically you could do something like this

has_permission_on :comments, :to => :read, :join_by => :and do
  if_attribute :commenable_type => is { 'Issue' }
  if_permitted_to :read, :commentable, :context => :issues
end

however it's not working for me.  which for comments I usually don't need to use it, as it's always a use can read anything on the commentable, and I only display comments when viewing the commentable.  but for cases where I do, I end up manually overrideing the with_permissions_to on that model..  

e.g. something like this.. Now, you need to make sure all of your other filters are BEFORE with_permissions_to in this case.. (it has to be LAST as it returns an array not an AR::Relation)

  # Override declarative_authorizations version due to lack of polymorphic support
  #
  # todo see if it's possible to incorporate this IN declarative_authorization or at least generalize
  #
  # Iterates through event objects from the database and checks if the current user CAN use the specified permission
  #
  def self.with_permissions_to(permission, *args)
    options = args.extract_options!.dup

    self.all(options).select do |e|
      e.permitted_to? permission
    end
  end



--
You received this message because you are subscribed to the Google Groups "declarative_authorization" group.

To post to this group, send email to declarative_...@googlegroups.com.
To unsubscribe from this group, send email to declarative_author...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/declarative_authorization?hl=en.
Reply all
Reply to author
Forward
0 new messages