I have an application where a user can be linked to several companies.
The manyToMany relationship with the company is a distinguished entity called Associate.
I'd like to give to this Associate entity the exact same role functionnality as my FOSUserBundle User entity has. Important : if a user has a role_manager for one company, it should not be given the rights to access specific features of another company he belongs to too.
Is there a clean way to do this?
I'd like to check for instance if $this->getUser->getAssociate->hasRole('ROLE_MANAGER') is true.
What if I give a role array to my entity Associate? I've read it's not secure enough? Why? What could someone do to break that security if anyway my users have to pass through FOS security login checks?
I've found an article where using a voter is suggested. But I don't want to filter routes, I really want to check the condition against the link between a user and a company, so if a voter is the solution, how would I use it?
EDIT: if a better solution not involving roles or with different logic exists, I am interested in learning about it!!
So in my case, I actually one user can actually be only linked to a maximum of 4 companies, each of a different kind defined by its category.
The official doc would suggest using ACL, defining a role for every company or store the data in the entity. cf first paragraphs of :
http://symfony.com/doc/current/cookbook/security/acl.html
I used a combination of roles and business logic. I've created roles for every type of company and since one user can only have one company per type, I just had to check for the type and the role-manager associated to the type.
See my voter here:
symfony2 call is_granted in voter : how to avoid an infinite loop?
Related
I have read about creating and responsibilities of aggregates and I have doubts how to correctly implement them. Assume that we have context within there are 2 entities. One is a Company and the second one is a User. Business rules are in the Company entity that means this should become aggregate root. To the Company we can assign ony 3 users and we can not assign User when Comapny has status "blocked". User has also possibility to login using emial and password. With that in mind every action on User entity should bo invoked thru the Aggregate root and User should not have it's own Repository. How to make login action on User when we can not do it directly without Company root? We can not call User out of the aggregate. How to find User with provided email and password? Fetching all Aggregates and iterating over their Users is inefficient and I think it's not a good idea.
Thank you for help.
I think that user should belong to another BC (that manages authentication and authorization). In your Company BC, you have to get the user from the authentication and authorization BC. You have to integrate both BCs with a context mapping pattern, where authentication and authorization BC is upstream, and Company BC is downstream.
Authentication usually isn't part of a domain (in 99% of all use cases), just part of the infrastructure.
As such Users shouldn't ever appear within a bounded context. In the real business world, there are no users neither, only People, Persons, Employees, Managers or Contacts etc.
So for logging concerns you have our users with username + password which serve as authentication. These users have an id (numerical, string or guid).
Your Employee or Persons entity/aggregate (or what ever you named it depends on your domain, the exact term depends from company to company - the ubiquitous language) then only contains the data which belongs to the person (but not identificaton related information).
You can then connect employees to users (either by having the employee id be the id of the users used for login, an extra field or via a 1:1 or 1:n lookup table.
This way you can easily delete a user (the login) without deleting the Employee entity, because in real world scenarios you can't easily just delete business data (i.e. imagine deleting a user removes the recipient on every invoice or CRM data, no one would ever know this person worked there in the past).
I've been reading about and playing with ASP.NET MVC lately, to figure out if it will be the new framework for an exisiting product.
The product consists of a multi-user website where the customers are created by me and added to their respective companies. Each user then has access to do some stuff, add data etc. in the scope of his own company.
How would I go about creating a structure like that in MVC?
I basically want to be the "super-admin" that can create new users, add them to companies and control their rights.
The regular users will also have different user roles (admin, user, guest) within their company.
I've got pretty much everything else set up (MVC and the Entity framework is awesome), but I just need this last layer of separation.
Any help is much appreciated.
There's really two pieces to this. The first is roles. Simply create a clear designation between roles for a company versus roles for the entire application, for example: "Admin", "CompanyAdmin", "CompanyUser", and "CompanyGuest". There, I literally mean "Company", not a placeholder for a specific company name. You should only have one set of roles applicable to all company users.
The second piece is a form of ownership authorization. Each user is assigned to a company, surely through a foreign key on your user entity. Your routes will contain some component that identifies the company being utilized, whether that be via a subdomain, or just part of the path, i.e. /FooInc/Bar/Baz. In your actions, you'll use this component to look up the company from your pesistence store and then compare that with the company the user is assigned to. If the two do not match, then you return a 403. Otherwise, you let the user proceed.
There's many ways that can be done. You could use an action filter, base controller, etc. That's largely up to you and the needs of your application. Regardless, ASP.NET MVC is very capable to handle such a thing.
I would like to find out all of the user which are associated in some roles. I have seen the UserLocalService that provides the method to find the users in a particular role. But I want a method to which I can pass an array of roleIds and it shall return me the list of users in those roles.
One way is to write custom SQL, but I would like to get it done by using the API only.
Is that possible with Liferay API??
Call the API multiple times? Create a new service that does this for you so that you only have a single call to (your) API?
I know, this is probably not the answer that you expected. Note that roles in Liferay can be scoped globally (to the whole portal, called 'regular') or to an individual site or organization. Thus just giving a roleId would limit you to the global roles (as the others would require the site's or organization's groupId).
Stepping back and looking at what you want to achieve, my first guess is that you have some semantics in being associated with a specific role - kind of like... a usergroup? A role is designed to give permissions to users, while a usergroup is designed to group users. UserLocalService also has getUserGroupUsers - this also only takes a single usergroup id, but at least it's a single (global) scope by definition and not ambiguous like roles.
Is there a quick way to mark a custom entity as readable by all users via a Customizations.xml entry?
I have been successful in creating the custom entity I need, but cannot seem to make it readable by newly created users without creating a security role (with read permissions for the entity) and applying it to ALL users.
Is there a way I can ensure that everyone (even newly created users) have read access to a custom entity?
Sorry the question, but why do you need an Entity for each user that is readable by everyone?
I mean is not the same to create a record in one entity and filter it with custom views if you want to?
Users need at least one role to be able to log in, so I'd suggest to create one common role that is assigned to everyone. Then you can grant permission to read your entity in this common role.
This approach might help you also in future, when you'll have to allow access to other entities for everyone.
I'm triying to develop an application which will contain different kinds of companies, and each company will have different roles.
This way, when a superadmin create a company, will define which roles can be attached to this kind of company.
For example, the superadmin could create a shopping center which could have a shop assistant and a director (each of them with different permissions); and another kind of companny which could be a coffee shop, which could have a waiter and a chef.
Then, when an user loggin inside the application, and will want to create a new user, will only have the possibility of select the roles of his kind of company.
But I can't see the way to develop, using the security.yml file and the FOSUserBUndle.
Thanks in advance!
For this kind of purpose, I think you need to implement your security logic inside controllers ; with security.yml you can restrict some entire areas, but I don't think it will help in your case. Maybe you can first define some routes that would be accessible only to some roles (for example, "/waiter/*" for waiters)
Then you can implement like a new kind of roles ; each company can have a field "possible_roles" that will be an array of roles. For example, if a superadmin creates a coffee shop, then you will have possible_roles = { "ROLE_WAITER", "ROLE_CHEF" }
After that you just have to check if the user's role is in the company role's array, and if he has access to the page.
Is it clear ?