Tuesday, 31 March 2009

State of authentication

We're using restful_authentication for login - because it's a good standard set of tools. However, we didn't want activation for our system, as it's just a slow-down on the path to user kick-ass-ness, and we wanted out users up and running with a minimum of fuss. However what we *did* want, was statefulness (so we could suspend users).

When I ran the usual generator without the --include-activation flag, I figured that would be the trick...

Unfortunately, AR doesn't seem to grasp that you can have statefulness without activation - so the authentication/authorisation sections have an activation state (and set up an activation code and require that you provide it and activate your user... etc) regardless of your choice of --include-activation.

This is a bit annoying - especially because the Authorization module is now also hidden deep in the bowels of the AR plugin itself (rather than in the user model), which means I can't just delete the bits I don't want.

The plugin itself is not clear about how to go about setting up your own set of states (eg removing activation, or adding a "locked" state), so this is a quickie guide.

Setting up your own states

To begin with, to override your states, you need to copy the appropriate Authorization file into your lib directory eg:
cp vendor/plugins/restful_authentication/lib/authorization/stateful_roles.rb lib/my_stateful_roles.rb

Then require this file at the top of your user model eg:
require 'lib/my_stateful_roles.rb'

Open up this file and change the module name so you don't clash (in the bizarre case you need to use the standard set of states in some other model) eg:

module Authorization
  module MyStatefulRoles

Your user model will then have a reference to this module that you need to update from Authorization::StatefulRoles to Authorization::MyStatefulRoles

You now have a file that you can alter to your heart's content.

Coming soon: how to successfully remove the activation state from this file...


Emlyn said...

I'm starting to feel that there are some definate problems to these generator based approaches to common tasks like login. Although much shunned, I still have a lingering suspicious that the engine based approach might be a better one, as it's able to be kept up to date with the latest features (eg, update your plugin to add openID support, and now with Rails 2.3, perhaps this idea should be revisited.

Taryn said...

Strangely enough, if the code had been generated (instead of in the plugin) it would have been better.

Generated code I can hack to make it work the way I want. It's when the implementation is hidden away some engine locked in a dim, dark dungeon (with no obvious way of overriding it) that I find it most difficult to work.

In this case - the states used to be generated and dropped into the model object - so I used to be able to delete the ones I didn't want and carry on from there.

It's always a balance between "it does it all for you" and "let me change it to the way I want". In this case - having statefulness taken care-of is great... but let me change the actual states myself!