Pregunta

Estoy trabajando en una aplicación web Rails, y actualmente está siendo utilizada por unos 20 usuarios.

Algunas partes de la aplicación solo son accesibles para algunos usuarios, por lo que ya tenemos un marco de autorización básico, que implementé utilizando el complemento Act_as_authenticated.

Los privilegios de los usuarios dependen del departamento en el que trabajan, por lo que, por ejemplo, la administración tiene acceso a todas las partes de la aplicación, mientras que la contabilidad solo tiene acceso a las partes relacionadas con la contabilidad, y las ventas solo tienen acceso a las partes relacionadas con las ventas. , etc.

Por otro lado, los usuarios ven los enlaces a acciones para las cuales tienen privilegios insuficientes. Por ejemplo, aquellos en el departamento de ventas ven un enlace a los registros financieros en el menú principal, pero cuando hacen clic en él, no sucede nada. Esto es así porque AFAIK no existe una manera eficiente de consultar los privilegios de los usuarios utilizando los actos como autenticados.

Quiero cambiar esto de dos maneras:

  1. Quiero introducir una autorización más detallada. Actualmente, la autorización se realiza a nivel de controlador. Quiero hacer esto a nivel de acción o modelo. Por ejemplo, quiero que aquellos en el departamento de ventas puedan crear y actualizar pagos, pero no eliminarlos.

  2. Quiero poder consultar los privilegios del usuario de manera eficiente, para poder eliminar enlaces innecesarios (y confusos) de la interfaz.

¿Cuál crees que es la forma más elegante de implementar esto?

Las respuestas específicas de Rails no son necesarias, solo quiero saber cómo se debe implementar esto en una aplicación basada en datos.

Finalmente, así es como se implementa actualmente:

def authorized?
  current_user.role.foo? or current_user.role.bar?
end

Y aquí está mi idea inicial, que creo que no es la mejor manera de resolver esto:

+------------+------------+---------+
| department | controller | action  |
+------------+------------+---------+
| accounting | payments   | index   |
| accounting | payments   | new     |
| accounting | payments   | create  |
| accounting | payments   | edit    |
| accounting | payments   | update  |
| accounting | payments   | destroy |
| sales      | payments   | new     |
| sales      | payments   | create  |
| sales      | payments   | edit    |
| sales      | payments   | update  |
+------------+------------+---------+

o

+------------+----------+-------+--------+------+--------+--------+
| department | model    | list  | create | read | update | delete |
+------------+----------+-------+--------+------+--------+--------+
| accounting | payments | TRUE  | TRUE   | TRUE | TRUE   | TRUE   |
| sales      | payments | FALSE | TRUE   | TRUE | TRUE   | FALSE  |
+------------+----------+-------+--------+------+--------+--------+
¿Fue útil?

Solución

El concepto básico de autorización, según tengo entendido, es un rol. El rol puede expresar varias cosas:

  1. relación de un usuario con el sistema en su conjunto (por ejemplo, ser un administrador del sistema)
  2. relación de un usuario con algún tipo de entidades (por ejemplo, ser un moderador de comentarios)
  3. relación de un usuario con alguna entidad particular (por ejemplo, ser propietario de algún recurso)
  4. alguna otra relación compleja (por ejemplo, ser amigo de un usuario propietario de algún recurso)
  5. ese usuario tiene algunos atributos o responde a algún mensaje de alguna manera particular (por ejemplo, ser un adolescente)

Un sistema de autorización realmente detallado debería permitirle definir el rol de un usuario en función de cualquiera de los criterios mencionados anteriormente. Además, debería permitirle establecer más de una función para un usuario. (Las formas más simples de complementos de autorización para Rails generalmente le permiten definir solo el primer tipo de roles y establecer un solo rol para un usuario).

La otra parte de la autenticación es un mecanismo que decide qué parte del código ejecutar (o no ejecutar) en función del hecho de si un usuario se ajusta a algún rol (conjunto de roles) o no. Para aplicar este mecanismo, tenemos que encontrar los puntos en los que debe tener lugar la autorización y seleccionar los roles para los que el código debe o no ejecutarse.

La forma que funciona para mí en Rails es definir roles en el nivel de modelo y dejar el mecanismo de autorización (establecer roles permitidos para partes del código que quiero autorizar y preguntar si el usuario actual tiene el rol permitido ejecutar la parte) completamente para controladores / vistas.

Para esto utilizo el plugin de autorización de rails modificado que tiene todas las posibilidades que acabo de mencionar incorporadas (varios tipos de roles, muchos roles para un usuario, autorización en el controlador y nivel de vista).

Otros consejos

puede que necesite introducir la noción de 'puntos de función' o 'características' en su modelo como puntos de control para el acceso; una 'característica' puede tener una 'característica principal' opcional para formar una jerarquía. Puede decidir qué es y qué no es una característica, y verifica los permisos mediante programación. Esto también debería permitirle verificar el acceso a nivel de función antes de dibujar un menú, de modo que los usuarios nunca vean enlaces a páginas a las que no se les permite acceder.

se describe una situación / solución similar aquí

De sus dos propuestas, la primera opción se ve un poco mejor ya que le permite agregar acciones que pueden no ser acciones a nivel de modelo. Supongo que se encontrará con un caso en el que el segundo modelo no hace lo suficiente, y tendrá que cambiar el esquema o comenzar a rociar la lógica de permisos en toda su aplicación (por ejemplo, '' Usuarios sin 'crear' el acceso tampoco puede ejecutar el método xxx ")

Creo que la razón por la que la solución no se ve muy SECA es porque hay repetición:

  1. En los nombres de departamento, y
  2. En las capacidades del departamento

Con respecto al # 1, tendría sentido crear una tabla de departamentos y asignar a cada departamento un Id.

Con respecto al # 2, estoy de acuerdo con el primer comentario. Probablemente pueda agrupar los diversos controladores y acciones en grupos funcionales, y luego establecer una relación de muchos a muchos (tabla de mapeo) entre usuarios y funciones. Las funciones tendrían una relación de uno a muchos con las acciones / controladores que permiten. Esto le permitiría, con una mínima repetición, decir cosas como "la contabilidad y las ventas deberían poder leer todas las tablas financieras".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top