I need help with a design

I have been working on an app but ran into many problems when i was applying authentication and authorization.

I want to have the following users with the given abilities.

Admin: full control on the entire system, but apart from login , email and password it does not require any more attributes

company owner: should be able to created the number of companies the admin approves, and have full control over all of its companies, i would like to send an invitation to this user type

user: should have different roles and has couple more fields than the company owner. The super user roles can only have full control over its own company. user cant create companies and should belong to a company and cant create companies. owners or super users should be able to create them via a crud

client: if approved by the admin a company is clients are allowed to log in to the system, they only have read access to their personal data and an internal email system. Have lots of fields, ca be affiliated to a company but the admin has access to all clients in the system. company owners only have access to their companies clients , and the users only to the clients that are affiliated to their company.

the problem comes now, I have 4 models at the moment, i would like authentication an authorization systems to be common to all of them. I have 4 abilities with cancan, and 4 resources with devise, but keeping up with everything was very redundant, i have 4 login page 4 path to signout, etc. If i unify all users in a single model an manage everything with fields in the DB im a little confuse on how to handle the company users relation since companies belong to owners in the current design but a company has many users and clients.

I have been thinking of a has many through association with resources called ownership, employ and affiliation and use boolean fields or a user type field to differentiate each type of user. I would need a lot of conditional validations of course. would STI be helpful or would it require 4 of everything anyway? i want to have one login page and one ability class.

Anyone has a better solution? i would appreciate some comments on this.

please help!! T_T

bump

anyone?

I have been working on an app but ran into many problems when i was applying authentication and authorization.

I want to have the following users with the given abilities.

Note your wording here, you want the following _users_. That is the clue to what follows.

Admin: full control on the entire system, but apart from login , email and password it does not require any more attributes

company owner: should be able to created the number of companies the admin approves, and have full control over all of its companies, i would like to send an invitation to this user type

user: should have different roles and has couple more fields than the company owner. The super user roles can only have full control over its own company. user cant create companies and should belong to a company and cant create companies. owners or super users should be able to create them via a crud

client: if approved by the admin a company is clients are allowed to log in to the system, they only have read access to their personal data and an internal email system. Have lots of fields, ca be affiliated to a company but the admin has access to all clients in the system. company owners only have access to their companies clients , and the users only to the clients that are affiliated to their company.

the problem comes now, I have 4 models at the moment, i would like authentication an authorization systems to be common to all of them. I have 4 abilities with cancan, and 4 resources with devise, but keeping up with everything was very redundant, i have 4 login page 4 path to signout, etc. If i unify all users in a single model an manage everything with fields in the DB im a little confuse on how to handle the company users relation since companies belong to owners in the current design but a company has many users and clients.

I presume that your models are Admin, Owner, User and Client (or similar names). The fact that you worded your initial requirement as I have pointed out above suggests that these are all Users with different roles. This rationalisation will mean they can all log on via the same page. Once logged in you can control the features available using the roles that a particular user has. There will likely be a roles table. User belongs_to role, Role has_many users and so on. The settings in the role will indicate what a user can do.

Colin

@colin

Thanks, someone finally cared.

I presume that your models are Admin, Owner, User and Client (or

similar names).

yes exactly, but i created separated models because there would be a lot of conditional validations if i didnt, for example owners can manage a companies but a user should belong to a company.

The fact that you worded your initial requirement as

I have pointed out above suggests that these are all Users with

different roles.

yes but i would require different controllers and views for each roles/type of user, and what i call user, which is the company employee in this case, has many roles.

User belongs_to role, Role has_many users

and so on.

im already think of making this a HBTM association, since , but only for the “user” role/type since is the one with many roles.

I though about all this before, but the reason i have hesitated to do it this way is because of the validations, excess in attributes

for the roles/types that dont require them and possible security issues.

I see not way of avoiding the creation of a very fat user model, with lots of accesible attributes dynamically changing and lots of scopes.

@colin

Thanks, someone finally cared.

I presume that your models are Admin, Owner, User and Client (or similar names).

yes exactly, but i created separated models because there would be a lot of conditional validations if i didnt, for example owners can manage a companies but a user should belong to a company.

I don't see that as a problem.

The fact that you worded your initial requirement as I have pointed out above suggests that these are all Users with different roles.

yes but i would require different controllers and views for each roles/type of user, and what i call user, which is the company employee in this case, has many roles.

You have that already with the different models. You can either continue with separate controllers/views or merge them as seems most appropriate. Remember a controller does not need to map to a model.

User belongs_to role, Role has_many users and so on.

im already think of making this a HBTM association, since , but only for the "user" role/type since is the one with many roles.

I though about all this before, but the reason i have hesitated to do it this way is because of the validations, excess in attributes for the roles/types that dont require them and possible security issues.

I see not way of avoiding the creation of a very fat user model, with lots of accesible attributes dynamically changing and lots of scopes.

Again that is not necessarily a problem, though it is all a matter of degree of course. If you really think that here you have different types of users rather than users with different roles you could look at STI as an alternative.

Colin

Remember a controller does not need to map to a model.

Yes i know, thanks.

Again that is not necessarily a problem, though it is all a matter of

degree of course.

If you really think that here you have different types of users rather

than users with different roles you could look at STI as an

alternative.

Well i know is not a problem, but i wanted to know if there is a better way to do all this. STI creates a problem when authenticating user and creating permissions, i would need an ability and a login per user type.

Hi,

Your task is cannot be that complicated, but for first reading it seemed, and a bit long.

Try to draw it first! First you have to find out: the user experience! It will make clear what datas you need, so what models, which kind of controllers you have to write with different actions. And from this writing a before filter will be easier. You haven't wrote how you solved the user authentication - from scratch? In FireFox there is an excellent Add-on, called Pencil, with this you can make a sketch easily!

Now I cannot spend more time with this, but write me in private more detailed, if you would like to, and in these days I will try to help. good luck gezope

Just to make things a bit more clear, my app will be very similar to shopify. Im worrying about this first and later i will worry about the CMS part.

Now I cannot spend more time with this, but write me in private more

detailed, if you would like to, and in these days I will try to help.

good luck

gezope

Thanks a lot. How can i get in contact with you?

Hi,

Your task is cannot be that complicated, but for first reading it seemed, and a bit long.

Try to draw it first! First you have to find out: the user experience! It will make clear what datas you need, so what models,

I disagree here, the models required should not be based upon the user experience required but on the underlying objects in the real world - users, companies and so on in this particular case. Unless I misunderstand what is meant by 'user experience'.

Colin

Colin Law wrote:

Hi,

Your task is cannot be that complicated, but for first reading it seemed, and a bit long.

Try to draw it first! First you have to find out: the user experience! It will make clear what datas you need, so what models,

I disagree here, the models required should not be based upon the user experience required but on the underlying objects in the real world - users, companies and so on in this particular case. Unless I misunderstand what is meant by 'user experience'.

I agree with Zoltan -- and I suspect you do too -- in this sense: when I put together an application, I usually think first about how I want it to present itself to the user and what the user should be able to accomplish (and write Cucumber scenarios accordingly). Only as a result of making those scenarios reality do I write model classes or anything else.

In other words: first define what you want the user to do, and only then figure out the code to make it happen.

Colin

Best,

I think my point is that the identification of models that are required should not be based on what is required in views or what the user experience is as he moves around the site. It is based on considering the underlying objects in the system. So in the OP's case, whether he should have different models for user, owner and so on or have one model, user, with different roles is not principally to do with how the app should appear or behave, except in the very broadest sense that there is a requirement for such objects.

The whole design process is iterative of course, but I think I would rephrase your suggestion as follows: First think (and preferably talk) about the underlying objects in the system so as to get a first stab at the models required (not the code, just what the models are likely to be), then define what you want the user to do, and then figure out the code to make it happen. Round and round ad nauseum. That is not to say that I think this is the one and only 'right' way to do it. Different people's minds work in different ways and others may find an alternative design process suits them better.

Colin

Radhames Brito wrote:

I have been working on an app but ran into many problems when i was applying authentication and authorization.

I want to have the following users with the given abilities.

Is there any reason that you cannot usefully employ existing authentication mechanisms like Auth_Logic or Devise? And what about Declarative_Authorization? Is there any reason why this does not suit your authorization needs?

It seems to me to be a mis-application of effort to write from the ground up that which is already freely available and maintained for you.

I agree with Zoltan – and I suspect you do too – in this sense: when I

put together an application, I usually think first about how I want it

to present itself to the user and what the user should be able to

accomplish (and write Cucumber scenarios accordingly). Only as a result

of making those scenarios reality do I write model classes or anything

else.

In other words: first define what you want the user to do, and only then

figure out the code to make it happen.

This approach should be very beneficial, i always begin by thinking of entities and their relations, and only when i get to the presentation layer i start thinking about the user experience. I will definitively try going this way to see if everything come out faster.

Is there any reason that you cannot usefully employ existing

authentication mechanisms like Auth_Logic or Devise? And what about

Declarative_Authorization? Is there any reason why this does not suit

your authorization needs?

It seems to me to be a mis-application of effort to write from the

ground up that which is already freely available and maintained for you.

creating a model for each user was the easiest way at first, but in that case i need a different login page for each and that detriments the user experience. Devise is awesome, but i have found it inflexible. I wanted to make an ajax login and it was harder than necessary. I tried to make all users login with one login page and i had to first learn how to use warden and hack devise quite a bit, in fact i did all that, but every change was like going against the concept devise was build for (easy of use , etc).

Authlogic is more flexible but it wont allow one page login for all users easily. Cancan requires a different ability per model so there is a lot of redundancy when i need to define permissions for one type of user and almost the same for another type of user. Thats why i have been thinking of joining everything in one model, but first i wanted to ask to see if that was the best/only way to overcome all those obstacles.

Colin Law wrote: [...]

The whole design process is iterative of course, but I think I would rephrase your suggestion as follows: First think (and preferably talk) about the underlying objects in the system so as to get a first stab at the models required (not the code, just what the models are likely to be), then define what you want the user to do, and then figure out the code to make it happen.

No, absolutely not. There is no point in thinking about the models involved before thinking about the desired functionality.

Round and round ad nauseum. That is not to say that I think this is the one and only 'right' way to do it.

No, of course there's more than one right way. But I think yours is one of the many wrong ways: it is inappropriate to start considering implementation details before you know what the implementation should do for the end user.

I'll turn the question around: why would you want to consider implementation before functionality? What possible benefits could it produce?

Best,

Colin Law wrote: [...]

The whole design process is iterative of course, but I think I would rephrase your suggestion as follows: First think (and preferably talk) about the underlying objects in the system so as to get a first stab at the models required (not the code, just what the models are likely to be), then define what you want the user to do, and then figure out the code to make it happen.

No, absolutely not. There is no point in thinking about the models involved before thinking about the desired functionality.

Round and round ad nauseum. That is not to say that I think this is the one and only 'right' way to do it.

No, of course there's more than one right way. But I think yours is one of the many wrong ways: it is inappropriate to start considering implementation details before you know what the implementation should do for the end user.

I'll turn the question around: why would you want to consider implementation before functionality? What possible benefits could it produce?

Well of course you need some idea of functionality before anything can be designed. If I can bring back a quote from your earlier post:

... when I put together an application, I usually think first about how I want it to present itself to the user and what the user should be able to accomplish (and write Cucumber scenarios accordingly). Only as a result of making those scenarios reality do I write model classes or anything else.

I am suggesting that there is a phase before considering in detail how the application should present itself to the user. For example to take the ubiquitous shopping app, before considering how the logon page should operate there is the decision that there will be users and that there should be a page where the user can logon. Similarly before considering how precisely the user adds a product to his shopping cart there is the decision that there will be products and shopping carts. It is at this stage that initial stabs at what the models will be can be made (note that I am not suggesting writing any code here, merely thinking about what the models will be). It does not seem feasible that one can write a Cucumber scenario for user logon and then go from that to the idea that maybe one needs a user model. Is it not true that the concept of a User must exist before one can write the scenario? Note again that I am not suggesting writing any code at this time, just thinking about what the models should be.

Colin

Colin Law wrote:

involved before thinking about the desired functionality. I'll turn the question around: why would you want to consider implementation before functionality? �What possible benefits could it produce?

Well of course you need some idea of functionality before anything can be designed. If I can bring back a quote from your earlier post:

... when I put together an application, I usually think first about how I want it to present itself to the user and what the user should be able to accomplish (and write Cucumber scenarios accordingly). Only as a result of making those scenarios reality do I write model classes or anything else.

I am suggesting that there is a phase before considering in detail how the application should present itself to the user.

There is the phase of deciding in very general terms what the broad goal of the application is -- in your case, something like "people should be able to order products from us".

For example to take the ubiquitous shopping app, before considering how the logon page should operate there is the decision that there will be users and that there should be a page where the user can logon.

Sort of. Out of the idea that users can order products comes the idea that we need a way to tell the system who's ordering. From that idea may come the fact that we want user accounts and a login interface. That's probably as far as I'd go down that particular path in initial requirements gathering with my client.

Similarly before considering how precisely the user adds a product to his shopping cart there is the decision that there will be products and shopping carts.

First step: Users should be able to order products. Second step: We want to present them a shopping cart interface to do so. Third step: Users should be able to do the following things from that interface.

The domain concepts emerge from requirements gathering. They are not considered before it so much as simultaneously with it in my experience.

It is at this stage that initial stabs at what the models will be can be made (note that I am not suggesting writing any code here, merely thinking about what the models will be).

No! It's premature. The business domain objects are a good start for guessing what model classes you'll need, but it's absolutely wrong to be thinking like a programmer when you're doing business analysis.

It does not seem feasible that one can write a Cucumber scenario for user logon and then go from that to the idea that maybe one needs a user model.

I assure you, it is entirely feasible. I do it all the time: write a Cucumber scenario with perhaps only the vaguest idea of what models I need, then start experimenting with the best way to make it pass. Remember, Cucumber scenarios are written in English for a reason: they're meant to test user-facing behavior, not code. You could completely rearchitect a system and still have the Cucumber scenarios pass.

Is it not true that the concept of a User must exist before one can write the scenario?

The business concept, sure. But it's premature to translate that into a concept of a User class in the requirements gathering stage.

(To be fair, user management is simple in most cases and requires a User class. But I've been doing stuff with my medical records application where I may have a bunch of features gleaned from the client and translated to Cucumber stories -- and still have no idea what the underlying models should look like.)

  Note again that I am not suggesting writing any code at this time, just thinking about what the models should be.

And I'm telling you that that's a bad idea. Don't think about models till you actually need to write them.

Colin

Best,

Radhames Brito wrote:

Authlogic is more flexible but it wont allow one page login for all users easily.

I do not understand what you mean by this. I have authlogic in production where there is but one authentication view used by every user. Each session created thereby has its own credentials and the user instance thereafter obtains its permissions from the declarative_authorization roles and rights configuration file.

I will not pretend that dealing with these two formidable packages was without its difficulties, particularly in the the beginning when my ignorance of them was complete. However, once one grasps the concepts upon which each is based then elaboration of the resulting security system is far easier than I ever thought possible.

Cancan requires a different ability per model so there is a lot of redundancy when i need to define permissions for one type of user and almost the same for another type of user. Thats why i have been thinking of joining everything in one model, but first i wanted ask to see if that was the best/only way to overcome all those obstacles.

I have not used CanCan (Ryan Biggs wrote that for one of his Railscasts episodes did he not?) but from what I can gather from your other messages it seems that you conflate authentication with authorization at several points. Authlogic, Devise and similar packages simply identify a particular set of credentials as having a unique accessor instance in the system. Declarative_Authorization and CanCan type packages tie access to specific bits of the application to specific accessor identities. Both need some form of implementation of the idea of a session to be of much use.

My own experience with RBAC is that it proves best to stay away from things that you do not fully understand until you need to address them directly and can afford the time to master the intricacies involved. Imagining what you will need in the absence of concrete requirements is a great time waster.

For an initial implementation of authentication and authorization I would create some minimal methods in the application controller to handle hard coded identities, rights and roles and then go ahead build the application. At some point the need for users will present itself and then you can implement your user models/classes modifying the stub methods to handle authorization alone. When authorization becomes the natural focus of development then it is time to look at things like Authlogic and CanCan.

I think that you will find the this approach permits you to remain focused on the value-added part of your project and leaves the administrative pieces on the periphery until their requirements are largely defined by the rest of your application.