Buenas, en esta ocación tengo una duda conceptual sobre cuando es ideal crear un security voter y cuando no, tengo algunas aplicaciones donde el usuario puede ejecutar ciertas acciones solo si se cumplen algunas condiciones, ejemplo:
Tengo un listado de productos, las acciones para esos productos son:
ver, editar, aprobar, rechazar, eliminar (esto es un ejemplo).
- Por ejemplo, editar y eliminar solo puede hacerlo el usuario que creó el producto (el dueño del producto).
- Solo se puede editar si no se ha aprobado el producto.
- Aprobar o Rechazar solo pueden hacerlo unos usuarios con un rol determinado (además de la lógica propia de que si un producto ya fué aprobado o rechazado no puede cambiarse su status).
Entonces mi duda es si por ejemplo el EditProductVoter debería solo verificar si el user logueado fué quien creó el producto, o si tambien debería verificar si el producto no está aprobado aun, quedando en una vista por ejemplo algo como:
Opción 1: (El voter verifica todo) {% if is_granted('edit', product) %} Opción 2: (El voter solo verifica el owner) {% if is_granted('edit', product) and product.status != 'approved' %}
Por otro lado, está el caso del ApproveProductVoter, debe el voter verificar el rol del usuario y el status del producto? o solo el status del producto?
Opción 1: (no crear el voter) {% if is_granted("ROLE_XXX") and product.status == 'to_be_approved' %} Opción 2: (que el voter solo verifique el status) {% if is_granted("ROLE_XXX") and is_granted("approve", product) %} Opción 3: (que el voter verifique status y rol del usuario) {% if is_granted("approve", product) %}
A la conclusión que he llegado es, solo crear un voter si se necesita comparar algo del objeto contra el usuario logueado, y no solo verificar status del objeto u otra cosa donde el usuario logueado no sea relevante.
Entonces, me gustaría conocer opiniones al respecto de cuando crean voters de seguridad y cuando no creen conveniente hacerlo.
Saludos!
Respuestas
La pregunta es muy interesante, pero me temo que no tiene una respuesta definitiva. Todo esto es bastante opinable. En primer lugar, la teoría de los voters es que permiten agrupar una serie de decisiones para saber si se concede o deniega un determinado permiso (ej. editar un producto) sobre un determinado recurso (ej. una instancia concreta de un producto).
Gracias a los voters puedes simplificar tu código mucho (no tienes que añadir un montón de if(...)
combinados con isGranted(...)
y puedes reutilizar esas condiciones de seguridad en cualquier parte de la aplicación (controladores, plantillas, servicios, etc.)
En el caso concreto que nos comentas, yo sí que incluiría en el voter la condición de que el producto esté aprobado. Para mí, esa es simplemente una más de las condiciones que se deben cumplir para poder editar el producto y por tanto, debería abstraerse en el voter.
Otra cosa sería el caso de que tengas muchísimas condiciones y algunas de ellas sean muy importantes o se reutilicen en otros sitios. Entonces sí que haría más de un voter para agrupar todas esas condiciones.
@javiereguiluz
Muchas gracias por tu respuesta Javier. Si basicamente no existe una opción correcta o incorrecta acá, por eso quería saber de otras opiniones para ver si estaba muy alejado de las tendencias y/o visión de otras personas en este aspecto.
Es una duda que ha venido dando muchas vueltas en mi cabeza, ya que por ejemplo la condición de solo aprobar un producto si esté no ha sido aprobado o rechazado previamente, es una verificación que debería hacerse hasta en un caso hipotetico de una aplicación que no implemente seguridad. Es por ello que me da la impresión de que esta condición que expongo de ejemplo realmente no tiene nada que ver con la seguridad y la autorización (en cuanto a un usuario contra un recurso), si no que es algo más genérico.
Bueno de todas formas muchas gracias nuevamente, es bueno siempre conocer la opinión de personas tan importantes en la comunidad. Saludos!
@manuel_j555
Si estar o no aprobado es algo que compruebas una y otra vez, quizás podrías usar para ello los filtros de Doctrine. Por si no los has usado antes, los filtros de Doctrine permite añadir condiciones a la consulta automáticamente (por ejemplo para que te añada and producto.status = 'aproved'
en todas las consultas de productos).
@javiereguiluz
Si los he usado, son bastante utiles para manejar filtros de forma automatica en muchas partes de la aplicación.
Sin embargo no estan relacionados con lo de los accesos, a lo que me refiero es algo más del tipo "Poder realizar cierta tarea si se cumple una condición o unas condiciones", es decir, solo se puede aprobar si el producto no estaba aprobado, además, solo debería aparecerle al usuario la opción de aprobar, si se cumplen las condiciones para que un producto sea aprobable.
Allí es donde me choca un poco usar un voter, porque es una condición un poco fuera del contexto de la seguridad de los usuarios y más relacionado a la lógica del negocio en cuando a la administración de productos. Porque en teoría que un producto sea aprobable o no, no depende de si se implementa seguridad o no.
@manuel_j555