Jabberwocky

Cancan: after a closer look

Posted in rails by elisehuard on March 13, 2010

Well, we’re into our first weeks of using cancan, and my earlier enthousiasm has been tempered somewhat.
It turns out that Cancan, although being well-written, is an Opinionated plugin. It may have been intended only for very simple applications.

Let me explain. Authorization happens mostly at controller level. Cancan offers sweetened before_filter for this purpose.
One being:

load_and_authorize_resource

which will do some standard loading action for you (nesting is possible). It is implied that the model has the same name as your controller, let’s say a CommentsController will load and authorize based on the model Comment.

It’s made flexible to a certain extent, because you can specify another model, like

load_and_authorize_resource :class => Post

Besides that, you can decide to use your own before_filter to do your own custom loading of the model.
If you don’t want to load, you can use

authorize_resource

(without the load)

But for me we’re already in muddy waters, First off, I want authorization only, it’s unnecessary to load the instance variables for me, that’s not what I expect from this plugin. So I’ll stick with authorize_resource.

Secondly, we’re wanting to authorize a resource, not a model A resource, as in REST, should be disconnected from the model, that’s implied in the MVC pattern. The resource is what we expose to the outside world, whether as URL or in a more general API. Models are the developer’s business and nobody else’s. Linking both is awfully restrictive: usually, you’ll also have controllers that use several models, controllers that use a cache or set off background tasks etc.

This is possible with Cancan in a rather roundabout way, by using symbols when defining an authorization rule and making a before_filter.

This is why I decided to fork and add the required behaviour to the plugin. To quote what I added to the README:

If the resource is not linked to a model, you can use the authorize_resource filter with the :resource option. When the resource name is the controller name, use

authorize_resource :resource => :controller

(for instance CalendarsController will authorize on :calendar)
When another name is required, a symbol can be used.

 authorize_resource :resource => :coffee

This may be enough for us to be able to work with it … we’ll see.
Update: Hooray ! as of version 1.1.0, cancan now takes :resource (not class), and there have been many nice additions/changes besides. My fork can now quietly disappear. Thank you Ryan Bates !

Tagged with: , , ,

Choosing an authorization framework for rails

Posted in rails, ruby by elisehuard on February 26, 2010

At my main customer’s we needed to choose an authorization framework. This is for a complex enterprise application, and requiring fine-grained authorization on:

  • roles
  • actions
  • model: most users can only access their own objects.

I’d had a look around, and after some digging ended up looking at 3 plugins, Declarative Authorization, grant and cancan.

Grant fell off almost immediately. It centered all authorization in the model, and I felt it was a bit too lightweight for our application.

Then I looked at declarative authorization and cancan.
At first sight, declarative authorization looked like a winner: I’m a believer in open source natural selection, and with about 650 people watching the plugin on github, it looked like a lot of people had found it a good fit. It’s also been lovingly polished since september 2008, so the kinks have probably been ironed out.

I cloned both plugins, and looked at the code and documentation.
Cancan is partly based on declarative_authorization. What struck me at first sight, is how simple cancan looked. Much less code, much less meta-monkey-magic. And a very friendly DSL and documentation.

And get this: I ran reek on both plugins (it’s a hobby of mine). And cancan came out practically clean ! That’s like having an alien in the living room ! It *never* happens ! Run reek on your own code, just for laughs, and you’ll see what I mean.

So we ended up choosing cancan, although declarative_authorization might have more features out of the box, we feel we’ll be able to extend cancan with much more ease, if at all necessary. It feels better to have a clean, fathomable codebase, than a larger engine. I’m aware that cancan has the unfair advantage of having learned from its predecessors, and kudos to the maintainers of declarative_authorization for having inspired others.

Note: I’m aware there are quite a few other plugins out there. If you found another one and you’re very happy about it, please share.

Tagged with: , , ,