Renderizar vistas según tu nivel de usuario

Veréis, quiero aprovechar los scaffolds que me genera Rails y la
identificación de usuarios para no estar creando acciones y
controladores independientes para la vista de administración y para la
de usuario, es decir, quiero que cuando un administrador se conecte al
sitio aparezcan todos los link_to a todas las acciones que se puedan
realizar en la página (el administrador por tanto vería la aplicación
entera) y que el usuario sólo pueda ver las que yo permita.

Imagínense un ejemplo sencillo como es un scaffold, deseo que si un
administrador está logueado pueda acceder a todas las acciones y sin
embargo si se ha detectado un usuario normal sin privilegios sólo pueda
acceder a la de show.

¿Cómo puedo llevar esto a cabo?

Agustin Viñao wrote:

Fijate estos screencasts de Ryan B. que muestran una forma de
organizar
lo que necesitas:

#19 Where Administration Goes - RailsCasts
#20 Restricting Access - RailsCasts
#21 Super Simple Authentication - RailsCasts

plantean una forma simple de autenticacion pero lo podes modificar de
forma
muy facil para que se haga con algun plugin de autenticacion general, lo
importante de estos screencasts es ver como cambia lo que se visualiza
segun
el user o nivel de acceso.


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

Estoy usando authlogic, con crear un campo booleano para el usuario que
sea falso si no es administrador y verdadero si sí lo es, podría
implementarlo ¿No?

Gracias ;).

Depende de como tenes armada la aplicacion, generalmente eso se hace por
una
definicio de rol para el usuario (con algun plugin por ejemplo) y asi
tener
algun helper por ejemplo para preguntar si es admin, como veras en los
screencast vas a tener un helper que con preguntar:

<%if admin?%>

Eliminar...
<%>end%>

podras manejar lo que vas a mostrar o no.

En tal caso si queres manejar con un flag en el modelo de usuarios,
armas un
metodo para preguntar

<%if user.admin?%>


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

Fijate estos screencasts de Ryan B. que muestran una forma de
organizar
lo que necesitas:

plantean una forma simple de autenticacion pero lo podes modificar de
forma
muy facil para que se haga con algun plugin de autenticacion general, lo
importante de estos screencasts es ver como cambia lo que se visualiza
segun
el user o nivel de acceso.


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

Una aproximación que podría ser más chula podría ser algo como
#/helpers/application_helper.rb
module ApplicationHelper
def for_admin
current_user.admin? ? yield : nil
end
end

En la vista

<%= for_admin{ link_to ‘Borrar’, borrar_model_path(model)} %>

O en modo bloque

<% for_admin do %>
<%= link_to ‘Borrar’, borrar_modelo_path(modelo) %>
<% end %>

Aviso, no lo he probado, pero salvo error, debería funcionar, y parece
una
manera bastante limpia si es exactamente lo que necesitas.

Un Saludo


Guillermo Álvarez

Sent from Madrid, Comunidad de Madrid

Guillermo wrote:

Una aproximación que podría ser más chula podría ser algo como
#/helpers/application_helper.rb
module ApplicationHelper
def for_admin
current_user.admin? ? yield : nil
end
end

En la vista

<%= for_admin{ link_to ‘Borrar’, borrar_model_path(model)} %>

O en modo bloque

<% for_admin do %>
<%= link_to ‘Borrar’, borrar_modelo_path(modelo) %>
<% end %>

Aviso, no lo he probado, pero salvo error, debería funcionar, y parece
una
manera bastante limpia si es exactamente lo que necesitas.

Un Saludo


Guillermo Álvarez

Sent from Madrid, Comunidad de Madrid

Sí, esa forma me parece más limpia para ahorrarme código lógico en las
vistas, dado que realmente los únicos roles en mi aplicación son el
administrador y los usuarios ¿Ves necesario usar un plugin de
autorización o mejor usar el recurso del booleano en el User?

Agustin Viñao wrote:

Depende de como tenes armada la aplicacion, generalmente eso se hace por
una
definicio de rol para el usuario (con algun plugin por ejemplo) y asi
tener
algun helper por ejemplo para preguntar si es admin, como veras en los
screencast vas a tener un helper que con preguntar:

<%if admin?%>

Eliminar...
<%>end%>

podras manejar lo que vas a mostrar o no.

En tal caso si queres manejar con un flag en el modelo de usuarios,
armas un
metodo para preguntar

<%if user.admin?%>


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

He estadomirando el plugin rails-authorization-plugin pero no entiendo
muy bien como utilizar el plugin ya que no sé como se aplican los roles
a los usuarios, ¿Conoces de algún tutorial para cogerle el tranquillo?

EL problema que veo de presentar un campo booleano es que estas
“ensuciando”
la informacion del usuario por llamarlo de alguna manera, hoy tenes 2
roles
posibles, pero puede que despues se te agregue alguno mas, o mismo si
podes
plantear roles en forma independiente, solo definir roles para aquellos
usuarios que sean admins nada mas.

Algo rapido que encontre en google es:

Fijate tambien que en el repositorio del plugin tenes ejemplos de
codigos:

Donde la primer linea dentro del controller define que roles son
permitidos
y una vista accesible para el resto:

permit “rubyists and wanna_be_rubyists”, :except => :public_page

mismo tenes un codigo para disponer de helpers para toda la aplicacion
basados en el plugin:

Espero te sirva.


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

Guillermo entiendo tu opinion, pero tambien hay que resaltar que cuando
armamos una aplicacion, hay ciertas decisiones que van mas alla de la
sola
implementacion de un parecer en un instante del desarrollo, como
comentaba
en otra respuesta, por acumular atributos en un modelo para definir
pequeñas
cosas a medida que las vamos diseñando, podemos terminar con un problema
de
performance a medida que crece la aplicacion.

Siempre considero que hay ciertas lineas de desarrollo a seguir cuando
estamos armando una aplicacion, que van mas alla de si es algo muy
pequeño o
no.

Por ejemplo, saber que si estamos hablando de roles de los usuarios, por
mas
que en un instante tengamos solo 2 roles posibles, saber que el dia de
mañana si en alguna parte de la aplicacion tenemos problemas con esto,
saber
que el manejo de roles se maneja independientemente al usuario, es diria
en
resumen, una buena metodologia de saber organizar nuestro desarrollo.

O por ejemplo, como comenta Ryan B. en un screencasts [1] de no hacer
un
mass assignment, si dejamos que el flag admin se setee en el usuarios,
cualquier caso en donde se produzca un problema de seguridad con el
modelo
user, cualquiera puede tomar control de la aplicacion

[1] #26 Hackers Love Mass Assignment - RailsCasts


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Guillermo [email protected]

2009/4/20 Carlos Belizón [email protected]

¿Ves necesario usar un plugin de
autorización o mejor usar el recurso del booleano en el User?

Esa decesisión te corresponde a ti y tus necesidades. Si como dices un
admin
es un user normal con el flag de admin, admin corresponde a un flag.

Creas el campo admin, y ya está. Si algún día necesitas más… ya lo
cambiarás.

Rails es la máxima expresión del carpe diem llevada a la programación.


Guillermo Álvarez

Sent from Madrid, Comunidad de Madrid

Agustin Viñao wrote:

Guillermo entiendo tu opinion…

[1] #26 Hackers Love Mass Assignment - RailsCasts


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Guillermo [email protected]

Pero tengo un problema, a ver, a la hora de registrar usuarios, ellos no
pueden elegir si son administradores o no (como es lógico), entonces
¿Cómo asigno al usuario que yo decida que sea administrador dicho rol?

para asignar los perfiles, lo haras con un usuario con perfil admin, es
decir, tendras dentro de la misma aplicacion, para el usuario con perfil
admin un panel de control donde gestionar ese tipo de cosas.


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

Lo que podes armar, por ejemplo, es que una vez construida toda la
aplicacion, en la instalacion/deploy de la misma, te genere un usuario
administrador por default en la base de datos por medio de una
migracion. Al
fin de cuentas, el usuario admin puede ser un insert en users y roles.

Asi hacen la mayoria de los sistemas uno instala, ponen un usuario
automatico o sino te piden los datos d ese user en la isntalacion. Yo
considero que con crear un user en la instalacion/deploy alcanza.


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

Agustin Viñao wrote:

para asignar los perfiles, lo haras con un usuario con perfil admin, es
decir, tendras dentro de la misma aplicacion, para el usuario con perfil
admin un panel de control donde gestionar ese tipo de cosas.


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

Sí, pero mi duda es, si no puedo guardar en mi base de datos quién es
administrador ¿Cómo consigo declarar quién será mi primer administrador?

Agustin Viñao wrote:

Lo que podes armar, por ejemplo, es que una vez construida toda la
aplicacion, en la instalacion/deploy de la misma, te genere un usuario
administrador por default en la base de datos por medio de una
migracion. Al
fin de cuentas, el usuario admin puede ser un insert en users y roles.

Asi hacen la mayoria de los sistemas uno instala, ponen un usuario
automatico o sino te piden los datos d ese user en la isntalacion. Yo
considero que con crear un user en la instalacion/deploy alcanza.


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

Ajá, muchas gracias, ¿Mientras para probar la aplicación cargo el
usuario con una fixture por ejemplo?

2009/4/20 Carlos Belizón [email protected]

Pero tengo un problema, a ver, a la hora de registrar usuarios, ellos no
pueden elegir si son administradores o no (como es lógico), entonces
¿Cómo asigno al usuario que yo decida que sea administrador dicho rol?

Pues yo lo suelo hacer a mano en la base de datos.

Y como bien comenta Agustin, para evitar los mass_assigments, recuerda
poner
como protegido el atributo admin.

class User < AR:Base
attr_protected :admin
end

Aunque yo soy más de listas blancas con attr_accesible.

Lo que podes armar es una migracion exclusiva para insertar ese
registro:

script/generate migration admincreate

y en la migracion podes hacer algo como:

user.create(:username => ‘admin’, :password => ‘secret’)
user.role.create(:rol_id => 1)

user.save

PD: pongo los codigos para hacer el ejemplo digamos.
Este es un ejemplo de una migracion que arme en una app para agregar un
campo
class Borradornotas < ActiveRecord::Migration
def self.up
add_column :notas, :borrador, :string, :limit=>1, :default=>“0”
*Nota.update_all(‘borrador=0’) *
end

def self.down
remove_column :notas, :borrador
end
end
fijate que en la linea en negrita hago un update de todas las notas
anteriores para que quede bien el campo que le estoy agregando que tiene
un
valor default, en las migracion se puede hacer operaciones de cualquier
tipo
con los registros.


  Agustin Viñao

www.agustinvinao.com
agustinvinao (Skype)

2009/4/20 Carlos Belizón [email protected]

2009/4/20 Agustin Nicolas Viñao Laseras [email protected]

Guillermo entiendo tu opinion, pero tambien hay que resaltar que cuando
armamos una aplicacion, hay ciertas decisiones que van mas alla de la sola
implementacion de un parecer en un instante del desarrollo, como comentaba
en otra respuesta, por acumular atributos en un modelo para definir pequeñas
cosas a medida que las vamos diseñando, podemos terminar con un problema de
performance a medida que crece la aplicacion.

Por eso decía que la solución es cosa suya según sus necesidades.

Tal vez haya entendido mal el desarrollo ágil, metodología que me gusta
bastante. Me gustan pequeñas iteraciones sobre el producto, una
interacción
a grandes rasgos resuelve los problemas de esa iteración. Y no se hacen
planes a largo plazo. ¿Por qué voy a complicar una cosa con roles si con
decir que el admin es el que tiene el primer id, o si hay varios, añadir
el
campo de admin?

Cuando tenga problemas de rendimiento. Pues añado índices a la base de
datos, cuando vuelva a tener problemas, añado caches de vista/modelo,
etc…
Y cuando se me quede corta la máquina, añado otra máquina y pongo un
balanceador. Pero no me gusta caer en la optimización prematura,
optimizar
un producto, que todavía no se como va a ser.

Pero insisto es simplemente como me gusta desarrollar, lo que entiendo
yo
como desarrollo agil, que casi podría resumir en resolver los problemas
inmediatos que tengo. El futuro ya vendrá.

Siempre considero que hay ciertas lineas de desarrollo a seguir cuando

estamos armando una aplicacion, que van mas alla de si es algo muy pequeño o
no.

Perfecto. Eso lo veía mucho en desarrollo Java, cuando un producto tenía
que
estar muy definido antes de empezar la parte de diseño del modelo de
negocio
y antes incluso de ponerse a programar. Pararse a pensar todos los ´y
si…´
que pudiese tener la aplicación.

Por ejemplo, saber que si estamos hablando de roles de los usuarios, por
mas

que en un instante tengamos solo 2 roles posibles, saber que el dia de
mañana si en alguna parte de la aplicacion tenemos problemas con esto, saber
que el manejo de roles se maneja independientemente al usuario, es diria en
resumen, una buena metodologia de saber organizar nuestro desarrollo.

Bueno, para ti, será la buena. Para mí, insisto que no, y te pido que
respetes lo que yo creo que es bueno para mi o no. Para mi esa
metodolgía,
en desarrollo web, un desarrollo de un producto dinámico, incluso una
start-up, es totalmente erróneo. Hago la aplicación Diciendo que el
usuario
con id 1 sea el admin. Cuando necesite algo más… hago la migración y
creo
la columna admin. Necesito algo más y creo los roles. Pero como producto
dinámico que es… ¿Y si no necesito roles? ¿Por que voy a preocuparme
por
algo que todavía no ha llegado?

O por ejemplo, como comenta Ryan B. en un screencasts [1] de no hacer un
mass assignment, si dejamos que el flag admin se setee en el usuarios,
cualquier caso en donde se produzca un problema de seguridad con el modelo
user, cualquiera puede tomar control de la aplicacion

Efectivamente, si no sabes lo que es el mass_assigment ni como usarlo,
no lo
uses. Si lees la documentación de rails verás el attr_protected y
attr_accesible que implementa el paradigman de listas negras y listas
blancas sobre los parámetros del modelo.

[1] #26 Hackers Love Mass Assignment - RailsCasts

Lo siento, pero en cuanto a la seguridad sobre rails, no suele ver
posts de
2007.