Instantiating controllers?

The problem: Application sidebar needs to be able to determine which
links to display, based on which links a user can actually access. It
is important that the interface be DRY, as this is a security matter.

The proposed solution: For each controller, define an authorized?
method, and a before filter to redirect users if it fails. For each
link in the sidebar view, instantiate an appropriate controller
object, complete with params, and call authorized? on it, displaying
the link only if the response is true.

The HELP: I really don't see how to properly instantiate this
controller. I really, REALLY don't see how to do this in a rack
framework. In fact, it looks to me that what I want is to tear apart
the rack/rails boundary. :frowning:

Student Jr wrote:

The problem: Application sidebar needs to be able to determine which
links to display, based on which links a user can actually access. It
is important that the interface be DRY, as this is a security matter.

DRY and security are orthogonal here. (And if it's a security matter,
make sure you consider the case where the user types in a URL of a page
he's not supposed to know about.)

The proposed solution: For each controller, define an authorized?
method, and a before filter to redirect users if it fails. For each
link in the sidebar view, instantiate an appropriate controller
object, complete with params, and call authorized? on it, displaying
the link only if the response is true.

You should never need to do it this way, for the reasons given below.
Anyway, this is asking too much of the controller (and it would be quite
inefficient)...and this only works at controller granularity.

What you might want to do is this: define your authorized? method on
User so you can do

if current_user.authorized? :controller => 'users', :action => 'delete'
  # show link
end

You could then use this same method in a before_filter in the controller
itself.

The HELP: I really don't see how to properly instantiate this
controller. I really, REALLY don't see how to do this in a rack
framework. In fact, it looks to me that what I want is to tear apart
the rack/rails boundary. :frowning:

Controllers are automatically instantiated in Rails. You have no direct
control over that, and needn't worry about it. The framework will do
the right thing.

--

You received this message because you are subscribed to the Google
Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to
rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.

Best,

Telling people about links that they aren't supposed to be able to
access sounds like a security issue to me.

More centrally, however, is that the links may be more complicated
than just http://site/controller/action. There can be any of a number
of things in the params, including an id field, and the interpretation
of these params can affect the results. But it is the target
controller which must interpret these params. For instance, the
target controller know which class is the class to use to interpret
the id field.

(Yes, I'm considering using this methodology more generally than just
a sidebar.)

Student Jr wrote:

Telling people about links that they aren't supposed to be able to
access sounds like a security issue to me.

Of course it is. That's not what I said.

And please don't top-post.

More centrally, however, is that the links may be more complicated
than just http://site/controller/action. There can be any of a number
of things in the params, including an id field, and the interpretation
of these params can affect the results.

Then send the whole url_for params hash to authorize?. Easy.

But it is the target
controller which must interpret these params. For instance, the
target controller know which class is the class to use to interpret
the id field.

Why does the id field need to get interpreted at this stage? Surely
you're not going to take each nav link and do a database query on the
record it talks about at the time the navbar is created -- that would be
horribly inefficient! Just reject the user when he loads the controller
tries to perform the action.

Also take a look at rails_authorization_plugin.

(Yes, I'm considering using this methodology more generally than just
a sidebar.)

Design for what you actually have now, not uncertain future
requirements. You can always refactor later. YAGNI.

I am not sure I know exactly what you mean, but just a suggestion to
DRY the thing: use inheritance of controllers and define the
before_filter there. Then I would suggest using partial for the bar
and include it in a layout. And since the actions are different for
each controller, i would suggest just a minimal type of controller
method returning just array of symbols like
[ :create, :settings, ... ] ... keeping the rendering and all the
other stuff as a responsibility of view and helpers.

good luck!

> More centrally, however, is that the links may be more complicated
> than justhttp://site/controller/action. There can be any of a number
> of things in the params, including an id field, and the interpretation
> of these params can affect the results.

Then send the whole url_for params hash to authorize?. Easy.

Thing is, url_for holds a lot of default information. It would appear
that I would need to walk ActionController::UrlRewriter#rewrite_url.
Doable, but messy. (Also fragile, if Rails changes)

> But it is the target
> controller which must interpret these params. For instance, the
> target controller know which class is the class to use to interpret
> the id field.

Why does the id field need to get interpreted at this stage? Surely
you're not going to take each nav link and do a database query on the
record it talks about at the time the navbar is created -- that would be
horribly inefficient! Just reject the user when he loads the controller
tries to perform the action.

No, the current_user object will cache any data of that sort. The
idea is to not even show the link in the first place.

Also take a look at rails_authorization_plugin.

I'll see if there is anything stealable there.

> (Yes, I'm considering using this methodology more generally than just
> a sidebar.)

Design for what you actually have now, not uncertain future
requirements. You can always refactor later. YAGNI.

I do have it now, the question is how far I can take the methodology.
If I only had controller/action - type links, then I would have
defined stuff at the class level & been done.