Topic: Help with authentication/authorisation design.

Could someone help me with an authentication/authorisation design please?

It's for a car garage application that allows a customer to monitor the status of their car. Here are my requirements:

1. I need a heirarchy of 4 users:
      A. Superuser (me)
      B. Garage owner.
      C. Mechanic.
      D. Customer.

The superuser can create/edit/delete users A,B,C and D.
The Garage owner can create/edit/delete users C and D.

2. There can be multiple Garage owners that own the same group of mechanics, and customers.

3. Authentication for garage owners and mechanics is an account number (that the application issues) and password.

4. Authentication for customers is based on their email address and password.

5. A single login form for all types of user.

6. A customer has visibility of the status of their car only. A mechanic or garage owner has access to all cars associated with the garage. And the super user has access to all cars in the db.

My plugins of choice for this would be authlogic and cancan, but I can't figure out a design that will represent the ownership of some users by other users, for example, that for a particular garage owner, get all the mechanics or customers.

I have tried several designs, but none seem to work. I would appreciate any help, advice or pointers.

Thanks

Re: Help with authentication/authorisation design.

Hi pingu,
well you need a mixture of things here and I think you would be better rolling your own solution (although devize may be worth looking at)
Theory (thinking on my feet a little here
1) Your user model could either be an STI or a polymorphic solution and I think in this case you want a polymorphic solution but I'm undecided on which is best at this stage so I'll come back to this

2) Whichever solution you end up with you will need the following classes
Admin (For the super user access)
GarageOwner
Mechanic
Customer

Plus the garage model
given that you have those classes as types of user you can pretty much set up the relationships and as you wish (I'm starting to lean towards STI)

An admin has many cars ~ (A simple scope on all cars)
garage belongs to GarageOwner
car belongs_to garage
mechanic belongs_to garage
mechanic has_many cars through garage

etc...

As far as logging in is concerned then I would use a mixture of the standard AWDWR way of doing this mixed in with omniauth (for logging in using twitter or facebook et al authentication) and I think this is where the devize gem can help you out

As far as who is allowed to do what is concerned there are different ways of achieving this, you have mentioned cancan, but it's simpe to roll your own.
I think you need to get to grips with devize first and see where that leads you (there are railscasts on this)

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: Help with authentication/authorisation design.

Thanks for the detailed answer James, I have a question about your solution. If I go the STI route, how do I handle the fact that a customer has a direct relationship with a car, where as the other users only have a relationship with a car through a garage?

Re: Help with authentication/authorisation design.

This is where I'm not sure if a polymorphic relationship is the right solution

From the cars perspective it belongs to a customer, and a garage (and possibly a mechanic?) so that's 3 potential distinct relationships with a user but it's still the same model so I don't think a polymorphic solution is really the correct approach here

For an STI solution the car table would need 3 foreign keys, 1 for the customer, 1 for the garage and possibly 1 for the mechanic allowing you to do car.customer car.mechanic and car.garage.

From a garage owners perspective you would need to define a has_many garages and a has_many cars through garages
from a garage perspective that would be a has_many cars
from an mechanics perspective you would again just need a has_many cars
and from a customers perspective again just a has_many cars

This enables you to do customer.cars, admin.cars, mechanic.cars

Which means you only have one user table
you have a class for each type of user and a corresponding id field in the cars table (except the admin doesn't need one as he goes through the garages relationship)

hope that makes sense

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: Help with authentication/authorisation design.

Thanks for your help James, it makes sense, and was a big help!

Re: Help with authentication/authorisation design.

I am writing here as it is an active blog and I have similar question.  I have 3 way user permissions: users without logged in, basic user logged in, and admin users which can edit info. Nothing works, every one can edit the dashboard, which i don't want to happen. I have following code in my ______________________________________________________________________________________________
class ApplicationController < ActionController::Base  protected   
def login_as_admim_required   
if session[:user]       
@user = session[:user]       

if @user.admin?                   
return true               
else            
flash[:warning]='You do not have enough permissions.'          
return false       
end   
else      
redirect_to signin_path, :notice =>

Last edited by takaloosingh (2011-05-31 11:28:59)