nathanl / authority

*CURRENTLY UNMAINTAINED*. Authority helps you authorize actions in your Rails app. It's ORM-neutral and has very little fancy syntax; just group your models under one or more Authorizer classes and write plain Ruby methods on them.
MIT License
1.21k stars 67 forks source link

Thoughts on Authority and Rails 4 view caching? #41

Closed nathanl closed 11 years ago

nathanl commented 11 years ago

Besides helping you declare permissions logic and enforce it, Authority facilities the familiar style of checking permissions in views: show a delete link if current_user.can_delete?(@widget).

In DHH's Railsconf keynote, he talked about how view caching runs into issues when different users need to see different things, as in our example here. He gives a quick example of a link with "data-visible-to" => 'admin creator' and says that Javascript can be used to "decorate" the page and show/hide those links as needed.

My question is: what, if anything, should Authority do to support this new approach in Rails 4?

Whatever we do, I also want to continue making Authority more usable outside of Rails, as @christhekeele has been helping with.

nathanl commented 11 years ago

(I should have also given a shout-out to @sanemat, who has already added Rails 4 testing. Thanks!)

amolpujari commented 11 years ago

What about you take control over rendering and when it calls any method on @object, check whether current user has required access to it, hence no need to put any conditional logic.

nathanl commented 11 years ago

@amolpujari - That would essentially mean disabling caching of any partial that needed a permission check.

christhekeele commented 11 years ago

I don't think Authority should get too involved in caching concerns or view logic.

Right now, the Views part of the docs is concise: if you want to do stuff conditionally, here's an example involving the tools available already in Authority.

The best way to empower Authority to handle this situation itself would be some custom view helpers. These could be easy (and fun) to write, but then we're a) prejudging how to solve a complicated issue for our users, b) adding another dependency to Rails (specifically ActionPack), c) hoping Rails doesn't change its mind too much in the future about how to do these things, and d) extending the scope and cognitive load of Authority into the rendering domain.

In short, I think trying to provide a generic solution would increase the amount of developer work to maintain Authority over time, without being robust enough to handle a validating enough number of situations.

Also, if Rails doesn't, somebody is sure to make some view helpers to easily generate this sort of cache-friendly template control flow based on a snippet of logic such as current_user.can_update?(@widget). Authority can integrate well into a lot of different situations because of its simplicity and well-defined scope.

Better to provide a quick rundown of the issue in the docs, along with some options and starting points, including a link to whatever version of DHH's technique ends up in the Rails docs, any gems that play well with Authority to solve the issue. This will also help us stay framework neutral.

nathanl commented 11 years ago

I like @christhekeele's emphasis on maintaining simplicity and framework neutrality. I think it's best to leave this out of Authority itself.

It might be useful to have a separate extension gem for this, however. It could give you a Rails engine to facilitate checking Authority permissions via AJAX. I'm imagining something like this:

  1. The page loads using view caches. Links that require permissions are hidden for all users and specially marked up to indicate the Authority calls needed to determine whether they should be shown.
  2. A piece of Javascript finds those on the page, gathers up info on all of them, and does a GET to an authorization controller
  3. The authorization controller looks through each authorization question and returns a bunch of boolean responses appropriate for the current user
  4. The JS uses that info to show some of the hidden links

Whoever needs this first (if anyone) could take a crack at it. :)

Another, simpler approach would be to hide any authorization-dependent view chunks at the bottom of the page, not nested inside anything, then use JS to replace the generic cached chunks on the page with the hidden, dynamically rendered chunk grabbed from the bottom. That has the advantage of not needing another round-trip to the server, and probably doesn't require a gem at all; just planning on the part of the app developer.

Thanks for helping me think through this!

christhekeele commented 11 years ago

I do like the idea of an AuthorityController to empower client-side applications.