I'm starting a new project which will act as an authorization/authentication server and a simple user management for certain type of users. A user can be a HelpDeskResponsible, GroupManager, Employee, Customer and more. All these groups members will be able to login with the same form on the web interface. Each model will contain different set of data describing them.
My problem is model design. I am pretty sure I need some User entity with all data necessary to login and read roles but I don't know how to associate rest of models with user account to easily fetch info about logged-in user. Another problem is users management - given user account is created I'd need to somehow link it to model of one of types I mentioned above.
Is my concept an over-engineering? Are there any solutions for such problem? Maybe I don't need multiple entities for different account types?
Thanks for any advice.
EDIT: Different permission levels are not the bigest problem here - I want to store different info about user depending on a role he belongs to. Customer will have different dataset than Employee. I'm pretty sure they are different models but I want to save an ability to login with the same login form.
I think the main problem is that your coupling goes backwards: in your case the user management context will have to know the details of other bounded contexts (BCs), whereas it should be the other way around. Otherwise, you will have to constantly modify your user management context as more systems use it.
For example, the HelpDeskResponsible role is most likely to be held in a Helpdesk system that lives in its own BC (or set of BCs). It is that context that should be responsible for modeling and persisting the details of a HelpDeskResponsible . The only thing the user management context should contain is whether or not a user has a specific role and perhaps some information that is generic to all users (eg first name, last name).
Obviously, the above diagram misses the anti-corruption layer (service(s), eg HelpDeskUserService ) that lives in HelpDeskUserService and is responsible for abstracting the coupling with User Management BC and translating User to HelpDeskResponsible .
Since your additional entities extend the User entity with some additional data, you would probably use Class Table Inheritance .
Class Table Inheritance is an inheritance mapping strategy in which each class in a hierarchy maps to multiple tables: its own table and the tables of all parent classes. The table of a child class is linked to the table of a parent class through a foreign key constraint. Doctrine 2 implements this strategy by using a discriminator column on the highest table in the hierarchy because this is the easiest way to achieve polymorphic queries with class table inheritance.
This way you will have a base table User with base data (username, password, email, etc) and then another table for each additional entity that extends User with additional data (e.g. salary column in Employee table) .
Here we are telling Doctrine that User is our base class. Doctrine then uses a discriminator column to identify which entity your user belongs to. Of course you have to map all the entities you want to extend from User (here I add only Employee ).
/** * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository") * @ORM\Table(name="user") * @ORM\InheritanceType("JOINED") * @ORM\DiscriminatorColumn(name="discr", type="string") * @ORM\DiscriminatorMap({"user" = "User", "employee" = "Employee"}) */ class User { // your class.. } /** * @ORM\Entity(repositoryClass="AppBundle\Repository\EmployeeRepository") * @ORM\Table(name="employee") */ class Employee extends User { /** * @ORM\Column(name="salary", type="float") */ private $salary; public function setSalary($salary) { $this->salary = $salary; return $this; } public function getSalary() { return $this->salary; } } Of course, the Employee class can override the main methods (for example getRoles() if you implement UserInterface on User ).
Finally (backup your database and) update your database schema with php bin/console doctrine:schema:update --force . Doctrine will create the new table with defined data plus a column id that refers to the relative User .
So when a normal user logs in, symfony will load the User entity, while when an employee logs in, it will load the Employee entity.