Estoy comenzando un nuevo proyecto que actuará como un servidor de autorización/autenticación y una administración de usuarios simple para cierto tipo de usuarios. Un usuario puede ser HelpDeskResponsible , GroupManager , Employee , Customer y más. Todos los miembros de estos grupos podrán iniciar sesión con el mismo formulario en la interfaz web. Cada modelo contendrá un conjunto diferente de datos que los describen.
Mi problema es el diseño del modelo. Estoy bastante seguro de que necesito alguna entidad de User con todos los datos necesarios para iniciar sesión y leer roles, pero no sé cómo asociar el resto de modelos con la cuenta de usuario para obtener fácilmente información sobre el usuario que inició sesión. Otro problema es la administración de usuarios: dada la cuenta de usuario creada, necesitaría vincularla de alguna manera al modelo de uno de los tipos que mencioné anteriormente.
¿Es mi concepto un exceso de ingeniería? ¿Hay alguna solución para tal problema? ¿Tal vez no necesito varias entidades para diferentes tipos de cuenta?
Gracias por cualquier consejo.
EDITAR : los diferentes niveles de permiso no son el mayor problema aquí: quiero almacenar información diferente sobre el usuario según el rol al que pertenezca. Customer tendrá un conjunto de datos diferente al del Employee . Estoy bastante seguro de que son modelos diferentes, pero quiero guardar la posibilidad de iniciar sesión con el mismo formulario de inicio de sesión.
Creo que el problema principal es que su acoplamiento va hacia atrás: en su caso, el contexto de administración de usuarios tendrá que conocer los detalles de otros contextos acotados (BC), mientras que debería ser al revés. De lo contrario, tendrá que modificar constantemente su contexto de gestión de usuarios a medida que más sistemas lo utilicen.
Por ejemplo, es muy probable que el rol de HelpDeskResponsible se desempeñe en un sistema de Helpdesk que vive en su propio BC (o conjunto de BC). Es ese contexto el que debe ser responsable de modelar y persistir los detalles de un HelpDeskResponsible . Lo único que debe contener el contexto de administración de usuarios es si un usuario tiene o no un rol específico y tal vez alguna información que sea genérica para todos los usuarios (por ejemplo, nombre, apellido).
Obviamente, el diagrama anterior pierde la capa anticorrupción (servicio(s), por ejemplo, HelpDeskUserService ) que vive en HelpDeskUserService y es responsable de abstraer el acoplamiento con User Management BC y traducir User en HelpDeskResponsible .
Dado que sus entidades adicionales amplían la entidad de User con otros datos adicionales, probablemente usaría Class Table Inheritance .
Class Table Inheritance es una estrategia de asignación de herencia en la que cada clase de una jerarquía se asigna a varias tablas: su propia tabla y las tablas de todas las clases principales. La tabla de una clase secundaria está vinculada a la tabla de una clase principal a través de una restricción de clave externa. Doctrine 2 implementa esta estrategia mediante el uso de una columna discriminadora en la tabla más alta de la jerarquía porque esta es la forma más fácil de lograr consultas polimórficas con herencia de tabla de clases.
De esta manera, tendrá una tabla base User con datos base (nombre de usuario, contraseña, correo electrónico, etc.) y luego otra tabla para cada entidad adicional que amplíe User con datos adicionales (por ejemplo, columna salary en la tabla Employee ).
Aquí le estamos diciendo a Doctrine que User es nuestra clase base. Luego, Doctrine usa una columna discriminadora para identificar a qué entidad pertenece tu usuario. Por supuesto, debe asignar todas las entidades que desea extender desde User (aquí agrego solo 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; } } Por supuesto, la clase Employee puede anular los métodos principales (por ejemplo getRoles() si implementa UserInterface en User ).
Finalmente (haga una copia de seguridad de su base de datos y) actualice su esquema de base de datos con php bin/console doctrine:schema:update --force . Doctrine creará la nueva tabla con datos definidos más una id de columna que se refiere al User relativo.
Entonces, cuando un usuario normal inicia sesión, Symfony cargará la entidad User , mientras que cuando un empleado inicie sesión, cargará la entidad Employee .