He usado gemas de autorización declarativa como cancan
y cancancan
en el pasado para controlar el acceso a los datos. Sin embargo, en esta nueva aplicación estoy tratando de controlar el acceso a las funciones reales.
Es su modelo SaaS típico, donde progresivamente hay más funciones disponibles según el nivel al que se haya suscrito.
La mayoría de las funciones están disponibles haciendo clic en diferentes íconos o elementos de menú en toda la aplicación.
Escribo para preguntar si hay un patrón de implementación bien conocido para esto que no conozco antes de lanzar el mío.
Estos son los diferentes tipos de cosas que se limitarán según el nivel de suscripción:
- Funciones accesibles por icono
- Funciones accesibles por elemento de menú
- Ciertos informes (cada uno de los cuales tiene una definición de informe que lo define).
- Ciertas cargas (cada una de las cuales tiene un FileType que lo define).
- Ciertos BackgroundProcesses (cada uno de los cuales tiene un ProcessType que lo define).
Cada suscripción tiene un plan. Es lo suficientemente simple como para vincular ese Plan en los elementos 3, 4 y 5 anteriores y utilizar cancancan
para accesibilidad por current_user
. Sin embargo, las características 1 y 2 son una historia diferente. Puedo ver envolviendo su accesibilidad en una vista auxiliar que verifica una lista de Características / Plan. Pero eso solo maneja la vista. Si el usuario conoce la URL, aún podrá acceder a la función escribiendo la URL directamente. En ese caso, ¿tengo que manejar la autorización nuevamente en el nivel de acción del controlador, o hay algún tipo de middleware que pueda poner para limitar la accesibilidad a las funciones?
Muchas gracias.
3 respuestas
Si es una aplicación simple, simplemente agrego una columna admin
en User
. Si hay más de 2 tipos de usuarios (admin / non-admin / author / editor / etc), lo convertiría en un campo Enum
en lugar de boolean.
Luego, dentro de user.rb
agrego varios métodos ...
def is_admin?
admin?
end
def is_author?
!admin?
end
A partir de ahí, también agrego un código en application_controller.rb
que genera una excepción:
def unauthorized
head(:unauthorized)
end
def unprocessable
head(:unprocessable_entity)
end
También agrego un método current_user
en application_controller.rb
:
helper_method :current_user
def current_user
@user ||= User.find(session[:user_id])
end
Luego, desde mi punto de vista, ahí es donde manejo cosas "ocultas" o deshabilitando botones.
<%= if current_user.is_admin? %>
<button>Admin button</button>
<% else %>
<button>Author button</button>
<% end %>
Por supuesto, esto NO es seguridad (solo cambia la capa de vista), por lo que también regreso temprano de los controladores usando los métodos anteriores que expuse:
def destroy
return unauthorized unless current_user.is_admin?
# ... delete code here
end
Para el ejemplo anterior, no olvide usar return o el código seguirá ejecutándose.
Para cosas que son más que simples, uso Pundit.
https://github.com/jnunemaker/flipper es una buena solución y hace exactamente lo que está buscando para.
De lo contrario, como dijiste, cancancan
es bueno para una solución ingenua.
Simplemente rodaría el mío usando enum para establecer diferentes niveles de acceso o suscripción. Luego solo escriba un before_action
llamado can_access?
para bloquear acciones enteras. Luego, establecería algunos condicionales o view_helpers en la vista para bloquear el acceso a ciertos elementos de la interfaz de usuario.
Nuevas preguntas
ruby-on-rails
Ruby on Rails es un marco de aplicación web full-stack de código abierto escrito en Ruby. Sigue el popular modelo de marco MVC y es conocido por su enfoque de "convención sobre configuración" para el desarrollo de aplicaciones.