Gestione ruoli utenti e controllers


#1

Salve a tutti,

sto creando un’applicazione web con rails che comprende un sistema di
gestione ruoli per gli utenti, ma ho qualche dubbio rispetto alla
gestione dei ruoli e l’architettura dell’applicazione.

Al momento gestisco 3 tipi di utenti: Amministratore > Capo Area >
Impiegato , dall’utente con privilegi maggiori fino a quello con
privilegi minimi.

Fin qui nessun problema, riesco a bloccare determinate azioni o interi
controller rispetto al ruolo. Quello che non riesco a strutturare in
modo pulito sono le situazioni dove piu utenti hanno accesso alla stessa
azione, ma devono vedere dati (estratti dal db) differenti.

Esempio:
Un Impiegato ha dei Documenti, nell’azione index del controller
documents dovrei mostrare tutti i SUOI documenti. Un capo area ha
accesso alla stessa azione dello stesso controller, ma vedere tutti i
documenti di TUTTI gli impiegati, un find(:all) in pratica.

Vorrei evitare condizioni nei controller in queste situazioni del tipo:
se sei capo area, fai un find(:all), se sei Impiegato fai un find solo
sui documenti dell’utente ecc…

Mi piacerebbe avere qualche input dalla community per capire come voi
risolvereste la cosa.

Grazie in anticipo!


#2

Serafino P. wrote:

Salve a tutti,

sto creando un’applicazione web con rails che comprende un sistema di
gestione ruoli per gli utenti, ma ho qualche dubbio rispetto alla
gestione dei ruoli e l’architettura dell’applicazione.

Al momento gestisco 3 tipi di utenti: Amministratore > Capo Area >
Impiegato , dall’utente con privilegi maggiori fino a quello con
privilegi minimi.

Fin qui nessun problema, riesco a bloccare determinate azioni o interi
controller rispetto al ruolo. Quello che non riesco a strutturare in
modo pulito sono le situazioni dove piu utenti hanno accesso alla stessa
azione, ma devono vedere dati (estratti dal db) differenti.

Esempio:
Un Impiegato ha dei Documenti, nell’azione index del controller
documents dovrei mostrare tutti i SUOI documenti. Un capo area ha
accesso alla stessa azione dello stesso controller, ma vedere tutti i
documenti di TUTTI gli impiegati, un find(:all) in pratica.

Vorrei evitare condizioni nei controller in queste situazioni del tipo:
se sei capo area, fai un find(:all), se sei Impiegato fai un find solo
sui documenti dell’utente ecc…

Mi piacerebbe avere qualche input dalla community per capire come voi
risolvereste la cosa.

Grazie in anticipo!

l’ultima volta che ho fatto una cosa simile ho fatto così :

Riscrivi il metodo find e fai in modo che aggiunga delle conditions in
base all’utente corrente in questo modo quando fai ad esempio
Documents.find(:all) la find lo riscrive mettendo ad es
Document.find(:all, :conditions => { :user_id => 1 })


#3

Oppure (supponendo che il metodo current_user restituisca l’utente
corrente):
u = current_user
user_documents = u.documents.find(:all)

Il 26 marzo 2009 20.59, Alessandro S. removed_email_address@domain.invalid ha
scritto:


Carlo P.
email: removed_email_address@domain.invalid
twitter: @carlopecchia


#4

Il 26 marzo 2009 14.08, Serafino P. removed_email_address@domain.invalid ha
scritto:

Vorrei evitare condizioni nei controller in queste situazioni del tipo:
se sei capo area, fai un find(:all), se sei Impiegato fai un find solo
sui documenti dell’utente ecc…

in una situazione simile, appunto per non rendere illeggibili i
controller né le view, io ho optato per una certa separazione: ho
definito in User dei metodi tipo may_create_documents?,
may_edit_document?(doc), etc., da usare nelle view per scegliere quali
link mostrare e nei controller per decidere se eseguire un’azione:

DocumentController.rb

def edit
@document = Document.find(params[:id])
if current_user.may_edit_document? @document

else

view.rb

<% if current_user.may_edit_document? @document %>
<%= link_to “edit”, … %>
<% end %>

per filtrare gli oggetti ho invece creato dei named_scope, tipo:

named_scope :visible_by, lambda { |user| user.admin? ? {} : {:user_id
=> user.id} }

così nel controller scrivo:

@documents = Document.visible_by(current_user).paginate …

(Quando poi i metodi in User sono diventati troppi, li ho spostati in
un modulo Permissions incluso da User.)

credo che definire un named_scope sia una soluzione preferibile al
ridefinire find, perché così, leggendo il controller, si capisce
chiaramente l’intenzione del codice, mentre se si ridefinisce find,
ciò non risulta evidente dal codice del controller, e si corre il
rischio di incappare in bug inspiegabili, specie a distanza di tempo.

pietro


#5

Grazie a tutti,mi sembrano tutti suggerimaneti validi. Alla fine,
analizzando meglio la situazione penso che opterò per una soluzione
leggermente diversa, dato che in diversi casi non cambia solo la query
ma anche quasi comletamente la view e altro codice del controller.

In linea di massima per i casi semplici in cui cambia effettivamente
solo la query, seguo i vostri consigli, e tengo un unico controller per
tutti gli utenti, mentre per il resto creo un namespace diverso per ogni
utente contenente un controller ad hoc, mi sembra la soluzione migliore
per mantenere flessibilità e pulizia.