I am trying to show here that Admin is a sub-class of User which is shown through the open triangle relationship connection. Is this enough to show that the sub-class relies on the main parent class to exist or would I then need to further apply composition? I have shown my example below. I am super confused regarding this. I feel it's enough to show it through the specialization arrow but I am not sure.
Is this enough to show that the sub-class relies on the main parent class to exist or would I then need to further apply composition?
Because of the generalization an Admin is a User, so if there is no User at all (User.allInstances()->size() = 0) then there is no Admin too. But of course you can have User(s) without having Admin.
If you just want to say that nothing more than the generalization is necessary.
But if you want to indicates an Admin is a User and there is 1 and only 1 admin you can do :
As you can see admin is a property of the class User (isStatic is true) because it is written underlined, no need to have it for all instances (including the admin(s)).
An other way to say the same without using an additional relation is :
Of course if you want to say there is at least one admin and not exactly one just use the multiplicity 1..* in the first solution or modify the constraint to have {allInstances()->size() >= 1} in the second solution.
I'd like to add another view to Bruno's excellent and accurate answer regarding generalization.
Yes, it is indeed sufficient to make Admin a specializatrion of User: this means that Admin is a User. It also means that Admin inherits User's non-private properties and operations (i.e. AuthenticateUser()). Finally it means that an instance a of Admin is also an instance of User and has hence a username and a password, although these are visible only to User instances. Unfortunately, once an object created as Admin, it will always stay an Admin.
Your hesitation about composition is therefore perfectly understandable: it is often advised to prefer composition over inheritance. You could perfectly imagine to have a User that has an Admin role, without Admin inheriting from User. But this is a radically different design. And in this specific case, it would be strange, if there wouldn't be other roles as well.
Last but not the least, it's worth to mention de decorator pattern that may combine inheritance with aggregation (instead of composition): In this design, you would make Admin a decorator of User: it extends the reponsibilities of the User with Admin responsibilities (i.e. with additional operations). But this can be done at runtime: you can create a User, add an Admin responsibility, or remove the Admin responsibility. THis is much more dynamic.
Related
Not sure if I'm going about this the "right" way.
In my application, I have recently had the requirement added for a second "type" of user. This means realistically I will need to route this user to a different controller than the primary type.
As a more concrete example:
The primary user of the application will be staff members. They will need to see company wide information.
Now, clients of the company will need to be able to log into the application, and see information specific to their needs (and no more).
Furthermore, there are likely to be more types of user in the future.
What is the "correct" way of designing/implementing this?
I think that, if you control the users role in the TWIG templates and showing them the only links that they could access (and, of course, protecting the routes with firewalls in the security.yml) may work.
I am building up a dynamic RBAC system for Yii and I don't know how to handle this problem:
The moderators can change the roles of the Users, furthermore the User can change it too by getting a different qualification (let's say achievement, so s/he can do more stuff and it can happen both ways).
What happens, when the role is changed Backwards (a role with less right) or Forwards (a role with more right) when s/he is logged in? Cannot access the functions he just got the right to use? Or can still access the functions until a logout/relog action?
Thanks your help in advance.
The effect of changing the authorization assignment will be inmediate.
Only the successive calls to IWebUser::checkAccess() issued in the same request may return cached values, since the default implementation of IWebUser, i.e. CWebUser, uses a static attribute to cache the calculated permissions.
To clarify the procedure, you will be calling IAuthManager::revoke() on the old permissions and IAuthManager::assign() on the new ones.
Edit
Sometimes you store session information through the IWebUser::setState() method; if the state of the currently logged user shall change along with the permissions, e.g. you store the current user's role name, you must take this into account and either call IWebUser::clearState() or IWebUser::logout() followed by IWebUser::login() –the latter also clears the cached permissions in the CWebUser implementation.
CWebUser::_access is declared private, so you will have to declare a new attribute if you want to override the default implementation.
The application is written in Ruby on Rails but the problem I am facing is more a design matter than language related.
the system provides service to a number of users to maintain a registry. So it relates persons to things. As such it has a model called Person representing owners and it has a model called User representing those who manage the registry.
Now a new requirement has arisen to allow People to log in and be able to change personal details which it was not required for the original design.
The question is how to refactor the application to allow this new requirement in?
One easy solution is to create Users for each person who request login credentials and link user to person entity but that is not very DRY as some fields such as firstname, surname etc. are in both classes and in particular, that is precisely the data people will be able to change. Besides User and Person are stored in separate tables.
The other possibility I was considering is to make one to extend the other but having data in separated tables it makes it a bit messy. Additionally the logical extension would be User <- Person as an user is (generally) a person but thinking on the implementation Person <- User is quite a lot easier.
One last option could be to scrap User and move login credentials into Person leaving logon fields empty for those who won't log in and half of the fields empty for those just login in.
Can you think of a better solution?
You could think about how this should ideally work if you were to write the application bottom-up, and then figure out how to make a reasonable compromise between that and your current setup. Here are some generic inputs.
As authentication is involved, you need an "Identity" that can be authenticated. This can be e.g. an email address and an associated password, with email verification.
An Identity can potentially be associated to multiple "Roles" and someone authenticated with the identity can choose which role to perform, e.g. "I am now an administrator" vs. "I am now a regular site user", and the role defines the user's current rights for the logged in identity. Or if you don't need that level of complexity, you can say that an Identity is a (single) Role.
You need some tracking between possible "Rights" and the Role the user is performing. E.g. the simplest setup could be the Identity or Role has some boolean can_edit_profile or can_modify_registry properties.
Whenever a user attempts to perform an action which requires certain Rights, it is simply a matter of looking up the corresponding rights set for the Role being performed by the user, to check whether the user is allowed to proceed.
For your application this may just involve adding a 'can_change_registry' property for your user objects, and check whether that property is True for any code accessing that part of the site.
My application domain has Users. It also has Organisations. Users can create Organisations.
My question is On which controller should I put the CreateOrganisations method? Does it belong on the UserController? Or does it belong on the OrganisationController? And how do I make that decision?
In any case, I plan to have an Add method on the Organisation model.
Any thoughts?
It belongs on the OrganizationController.
The Organization controller should be managing any creation/change to the organization model. The user should have no knowledge on how or what is involved in creating an organization. If you give them the ability to create organizations you are coupling logic. You make this decision because you have both a User and a Organization Controller.
If your user/organization don't really justify existence, aka they aren't really controlling much then merge them into one.
If both classes exist I vote for organization.
Like you said, a User can create an organization, so unless the organization doesn't tracks the owner (unlikely), you should have the CreateOrganization method delegated onto the user. A basic idea I can think of would be like:
User: Creates organizations by calling OrganizationRepository::Add( OwnerId )
Organizations: Can only be created given the id of the owner.
If (and only if) you don't need to track the creator of organizations, then the idea of placing an Add method directly on the organization without requiring anything else looks fine.
Hope I can help!
David
Does anyone have any tips as we develop an application that will require each user to be assigned a permission level. The permission level will determine what functionality is available to the user.
Any advice?
How would you (do you) employ such functionality in your application?
First you need to figure out what functionality you want to cover by your permission system, and in what detail:
Access to tables (List, CRUD)
Functions/Modules
Access on record level (=ACL)
Positive (grant) or Negative (revoke) semantics
What is the "admin" role allowed to do
If you want to restrict access to tables, you can easily set up an additional table containing all the table names, and grant select-list/select-record/insert/update/delete access to the roles/groups, as sketched by JV.
If you want to grant access to functions or modules, have a table of modules and grant execute to roles/groups.
Both functionality is equivalent to grants in SQL.
Access restriction on record level is much more complicated, as you need to model access rights on the status of a record (e.g. "public", "private", "released" in CMS apps), or have explicit permissions on each record.
If you want to implement a permission scheme equivalent to NTFS, you calculate the permission per record based on the group the user is assigned to, and have user-specific permissions that may override the group permissions, and revokes overriding grants.
My applications typically work on table+function / group level, which may be good enough, depending on your requirements.
This is the partial ER diagram for identity module in Turbogears, Python. It implements what you are looking forward to. Users are associated with groups and groups have associated permissions.
The two ways restricted feature availability can be implemented are:
(I prefer)In your controllers check the group to which the user belongs to and moderate your response to the View according to that. Thus View is just a renderer - no business logic.
The View gets the user details like groups and permissions and it decides what to display and what not to (MVC violated).
Read more about MVC (and Turbogears may be).
alt text http://jaivikram.verma.googlepages.com/temp.jpeg
It depends a lot of the language you use and the architecture of your application (web service ? client software ?).
For a server toy project, I though about assigning a minimum permission level to each command, and check it directly when a command network packet is received, triggering a permission error when the user hasn't a high enough level. I might not be suitable for another architecture.
It may be a bit of a dead end to pursue the concept of 'levels'. It may suit your current application, however a data model that consists of a mapping of roles to privileges is more general and suits most purposes.
Assign roles to users. A user may have more than one role, and their role(s) define the privileges they have. The concept is similar to groups, however 'role' is usually easily mapped directly to business logic (think of roles such as 'administrator', 'user', 'clerk', 'account manager', 'regional manager', etc). Privileges also map fairly directly to functions and data objects. You may also be able to map to implementations that use underlying platform access control (e.g. Java privileges).
In the controller code, you check (via their roles) that the user holds the required privilege to perform a function. It is also good practice to modify your views to hide functions that the user does not have the privileges to perform.
In your design you can visualise / document the access control system as a matrix (roles to privileges).