I need help with a design

I think we are just going to have to agree to differ on this one, though in fact I do not think our viewpoints are as far apart as it might appear from this discussion. I also think that you have to allow a bit of flexibility in approach for the different ways that different peoples brains work when analysing a system requirement. Looking back over my career I cannot remember any instances where I got in a mess or wasted significant time by thinking about the underlying objects too early in the analysis, but I can remember instances of problems when I left this phase too late. Of course the length of my career may have a bearing on what I can and cannot remember :slight_smile:

The one thing that I am sure we can agree on is the importance of making sure that what is provided is what the user wants, not what you think he aught to want or what his managers thinks he wants. Provided we achieve that then slight variations in the route to get there are not so important. Failing to understand the user requirements is the principle cause of IT system failures I think.

Regards

Colin

Colin Law wrote:

There is the phase of deciding in very general terms what the broad goal may come the fact that we want user accounts and a login interface. Third step: Users should be able to do the following things from that guessing what model classes you'll need, but it's absolutely wrong to be Remember, Cucumber scenarios are written in English for a reason: (To be fair, user management is simple in most cases and requires a User till you actually need to write them.

I think we are just going to have to agree to differ on this one,

I would rather not do that. In general, that's a sign that more discussion is needed, as one or both of us is probably missing something. Certainly I'm learning a lot from this discussion.

However, I'm perfectly willing to start a new thread for this.

though in fact I do not think our viewpoints are as far apart as it might appear from this discussion.

Quite probably not. As I think about it more, I do realize that I have a *slight* idea about my model class structure at the time I write my Cucumber stories. But then again, the steps that usually change the most are the explicitly model-related ones (Given a user exists with name: "Fred"...)

I also think that you have to allow a bit of flexibility in approach for the different ways that different peoples brains work when analysing a system requirement.

Maybe. I am not at all sure that this is a matter of cognitive style.

Looking back over my career I cannot remember any instances where I got in a mess or wasted significant time by thinking about the underlying objects too early in the analysis,

Not to be snarky, but would you really know? It's easy to do a premature analysis, get it wrong, and stick with it long after it should have been discarded. I've probably been guilty of this on occasion myself.

but I can remember instances of problems when I left this phase too late.

What sort of problems? In general, leaving it as late as possible seems like the right thing to do.

Of course the length of my career may have a bearing on what I can and cannot remember :slight_smile:

:slight_smile:

The one thing that I am sure we can agree on is the importance of making sure that what is provided is what the user wants, not what you think he aught to want or what his managers thinks he wants.

Right.

Provided we achieve that then slight variations in the route to get there are not so important. Failing to understand the user requirements is the principle cause of IT system failures I think.

Yes, I would think so, with hacking a close second.

Regards

Colin

Best,

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.

Because you have one user model i have 4, so when i authenticate i have to loop all the models to find the credentials beacuse there can be a company_user with name “pedro” and an admin name “pedro” because they are 2 diferent models, there is another problem because those 2 pedros could have

the same password, all because i am using different models for each user type.

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.

Oh have use then successfully before and they are quite easy to use, The problem is i tried out way of using them that is not commun

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.

ryan bates did, it only handles authorization, but all through an ability class and to this class you have to pass the user model on initialization, but since i have 4

models i need 4 ability class and switch them during login

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.

I agree with this to some point, but i hate refactoring , and i like to deal with the untested/new/hard stuff first so that if i dont find a solution with one strategy i can easily rebuild everything from scratch

Radhames Brito wrote:

Because you have one user model i have 4, so when i authenticate i have to loop all the models to find the credentials beacuse there can be a company_user with name "pedro" and an admin name "pedro" because they are 2 diferent models, there is another problem because those 2 pedros could have the same password, all because i am using different models for each user type.

Why the hell would you do it this way? Just use one user model with a role and have done with it. You're getting name conflicts and other problems the way you're doing it...so don't do it that way!

Best,

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.

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.

in my fourth comment im explained why i was doing it this way.

Radhames Brito wrote:

from my fourth comment

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,

That doesn't mean you need different models to go along with them.

and what i call user, which is the

company employee in this case, has many roles.

HABTM roles is perfectly feasible. You might want to use something like rails_authorization or CanCan to make managing privileges easier.

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.

Huh? No. A User is a User is a User, if I understand correctly. Stop trying to justify a bad design decision.

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.

There's nothing wrong with a fat model if it is the best representation for your data. But I'd be more inclined to use various has_ones for the additional information.

I'm doing something like this in a medical records app I'm working on, where clinicians and patients are both Users, but each patient record also has_one Chart to hold medical information that clinicians don't have stored.

Best,

That doesn’t mean you need different models to go along with them.

I wanted to keep the models thiner , but it does not seem to go well with authorization and authentication.

HABTM roles is perfectly feasible. You might want to use something like

rails_authorization or CanCan to make managing privileges easier.

Surely i will use is HABTM is im more worried on how to handle company owners, since they can exist before their companies do

but their employees should only exist after he creates a company, thats why i believe ill need a set of controllers and views for those main roles.

Huh? No. A User is a User is a User, if I understand correctly. Stop

trying to justify a bad design decision.

Im not justifying thats why am here asking you guys because i notice its a bad design and to note make a similar mistake again am asking for advise.

There’s nothing wrong with a fat model if it is the best representation

for your data. But I’d be more inclined to use various has_ones for the

additional information.

Yes colin told me that, but since everything before this project has been cleaner and direct i felt like that wasnt the “rails way”

I’m doing something like this in a medical records app I’m working on,

where clinicians and patients are both Users, but each patient record

also has_one Chart to hold medical information that clinicians don’t

have stored.

Very interesting approach, can you explain a bit more, how are you handling the conditional fields/validations?

I said this before but , the app im trying to build will be like http://www.shopify.com/ it should allow various scopes of administration/interaction , that’s why a have an admin,he is in truth the site administrator that controls the complete site , the company owner is the user that creates an account and pays a subscription fee for each company they create, what i call the user is a company employee that works interacting with that company’s clients and the client is the user to whom they give the service.

I am sorry to have to point out that the route you have gone down here supports Marnen's contention that model definition should not be started till the operational requirements are known. I imagine in your original spec you would have specified a single logon page (not four different ones). This is a clue that all the different types of users should be of the same (or derived) types.

:frowning:

Colin

Yes i see, the idea come after checking out how devise handles roles in their examples, devise uses a sort of scope and roles can be different models, so i figure using this appreach would let me avoid the creation one big fat user model, but it didnt work as expected.

Just take a quick look at devise and you will see where the idea come from.

Colin Law wrote:

[...] Because you have one user model i have 4, so when i authenticate i have to loop all the models to find the credentials beacuse there can be a company_user with name "pedro" and an admin name "pedro" because they are 2 diferent models, there is another problem because those 2 pedros could have the same password, all because i am using different models for each user type.

I am sorry to have to point out that the route you have gone down here supports Marnen's contention that model definition should not be started till the operational requirements are known.

Haha! Resistance is futile. You will be assimilated.

[...]

:frowning:

Colin

Best,

Radhames Brito wrote:

Because you have one user model i have 4, so when i authenticate i have to loop all the models to find the credentials beacuse there can be a company_user with name "pedro" and an admin name "pedro" because they are 2 diferent models, there is another problem because those 2 pedros could have the same password, all because i am using different models for each user type.

From what I have read I suggest that you reconsider what exactly a user is, what data is specific to a user and what data is specific to certain classes of users. It seems to me, taking your statement above as a guide, that you are confused as to the actual arrangement of things in the real world.

First, there is, and can only every be, one real person with the identity 'pedro'. There might be many people with similar names who are also known to your system but they are all different individuals. In a computer system, indeed in any organized filing system, some method of distinguishing between individuals other than by common name is required. Thus User IDs, SSNs, SINs, IRS IDs and so forth. Whatever the case, a given individual should have only one identity in a system and a single system identity should only ever refer to one individual.

Second, the attributes of a company belong in something that is related to that society in its own right and not to any individual associated with it.

Third, the user membership of a society is a separate issue as well. Consider that userid pedro might work for two companies at once. Or might work first for one company and then for a different company. This is an association or state that is distinct from either the user or the company even if it is dependent upon both.

In a similar fashion, user pedro might have superuser privileges for one company but only user privileges for another. As I understand your proposal this person would require an entry with one userid in the company-admin model and another in the company-user model and possibly even more entries for different company-user or company-admin model combinations. This is a maintenance nightmare that you are creating.

If instead you look at this from the point of view of entities and their relations then resulting data structure will be much more natural and will be easier to work with. So something like:

User 1---n CompanyUser n---1 Company plus            CompanyUser n---n UserRole n---n Role n---n RoleRight n---1 Right

Is likely a more flexible way to obtain the requisite functionality. If you go with AuthLogic and Declarative Authorization then after these are wired into your app all you are left to implement with respect to RBAC is in essence just:

Company 1---n CompanyUser n---n UserRole

Which strikes me as a bit more manageable.

Devise is an authentication system. The fact that it can be used to implement a primitive two-tier authorization system is a convenience for web apps that do not require a finer-grained approach to RBAC and wish to avoid the overhead of a full-featured RBAC implementation. I cannot see Devise's authorization functionality dealing with anything very elaborate for the reasons that have been discussed at length in this thread. Namely, it either requires a separate User model or a separate User attribute for each and every role.

The bottom line is that you have asked for advice. The advice that you are getting is uniformly against your chosen path. That is not to say that our advice is perfect or that your approach will fail. However, that seems the way to bet at the moment.

The bottom line is that you have asked for advice. The advice that you

are getting is uniformly against your chosen path. That is not to say

that our advice is perfect or that your approach will fail. However,

that seems the way to bet at the moment.

oh and i appreciate your advice very much, apparently every time i explain why i choose that path at the beginning readers think im jutifiying it, there is a confusion im not saying that the way i started is a good way , no no no, that design gave me a head ache but before refactoring i wanted to make sure the other options i was going to try wasnt wrong too (now im gona start with the features first and will create one user model with HBTM roles).

There seems to be some confusion, i was convinced that my first approach was is wrong since like the third reply you guys gave. Right now i just want to know if anyone has had a similar problem and can give me any tips.