Domanda

Sto lavorando su un'applicazione Web Rails ed è attualmente utilizzata da circa 20 utenti.

Alcune parti dell'applicazione sono accessibili solo ad alcuni utenti, quindi disponiamo già di un framework di autorizzazione di base, che ho implementato utilizzando il plug-in atto autenticato.

I privilegi degli utenti dipendono dal reparto in cui lavorano, quindi ad esempio l'amministrazione ha accesso a tutte le parti dell'applicazione, mentre la contabilità ha accesso solo alle parti relative alla contabilità e le vendite hanno accesso solo alle parti relative alle vendite , ecc.

D'altra parte, gli utenti vedono i collegamenti alle azioni per le quali hanno privilegi insufficienti. Ad esempio, quelli del reparto vendite vedono un link ai record finanziari nel menu principale, ma quando fanno clic su di esso, non accade nulla. Questo perché AFAIK non esiste un modo efficace per interrogare i privilegi dell'utente usando act_as_authenticated.

Voglio cambiare questo in due modi:

  1. Voglio introdurre un'autorizzazione più approfondita. Attualmente, l'autorizzazione viene eseguita a livello di controller. Voglio farlo a livello di azione o modello. Ad esempio, desidero che quelli del reparto vendite possano creare e aggiornare i pagamenti, ma non eliminarli.

  2. Voglio essere in grado di interrogare i privilegi dell'utente in modo efficiente, in modo da poter rimuovere collegamenti non necessari (e confusi) dall'interfaccia.

Quale pensi sia il modo più elegante per implementarlo?

Non sono necessarie risposte specifiche per le rotaie, voglio solo sapere come implementarle in un'applicazione basata sui dati.

Infine, ecco come è attualmente implementato:

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

Ed ecco la mia idea iniziale, che penso non sia il modo migliore per risolverlo:

+------------+------------+---------+
| 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  |
+------------+----------+-------+--------+------+--------+--------+
È stato utile?

Soluzione

Il concetto di base dell'autorizzazione, per quanto ho capito, è un ruolo. Il ruolo può esprimere varie cose:

  1. relazione di un utente con il sistema nel suo insieme (ad es. per essere un amministratore del sistema)
  2. relazione di un utente con un tipo di entità (ad es. per essere un moderatore di commenti)
  3. relazione di un utente con una determinata entità (ad es. essere proprietario di alcune risorse)
  4. qualche altra relazione complessa (ad es. essere amico di un utente che è proprietario di una risorsa)
  5. quell'utente ha degli attributi o risponde a qualche messaggio in qualche modo particolare (es. essere un adolescente)

Un sistema di autorizzazione a grana fine dovrebbe consentire di definire il ruolo di un utente in base a uno dei criteri sopra menzionati. Inoltre, dovrebbe consentire di impostare più di un ruolo per un utente. (Le forme più semplici di plug-in di autorizzazione per Rails di solito consentono di definire solo il primo tipo di ruoli e impostare un solo ruolo per un utente.)

L'altra parte dell'autorizzazione è un meccanismo che decide quale parte del codice eseguire (o non eseguire) in base al fatto se un utente rientra in un ruolo (set di ruoli) o meno. Per applicare questo meccanismo, dobbiamo trovare i punti in cui l'autorizzazione dovrebbe avere luogo e selezionare i ruoli per i quali il codice dovrebbe o non dovrebbe essere eseguito.

Il modo in cui lavoro per me in Rails è definire ruoli a livello di modello e lasciare il meccanismo di autorizzazione (impostazione dei ruoli consentiti per le parti di codice che voglio essere autorizzato e chiedere se l'utente corrente ha il ruolo che è autorizzato a eseguire la parte) interamente per controller / viste.

Per questo uso rails-autorizzazioni-plugin-tweaked che ha tutte le possibilità che ho appena menzionato integrate (vari tipi di ruoli, molti ruoli per un utente, autorizzazione sul controller e livello di visualizzazione).

Altri suggerimenti

potrebbe essere necessario introdurre la nozione di "punti funzione" o "caratteristiche" nel modello come punti di controllo per l'accesso; una 'caratteristica' può avere una 'caratteristica principale' opzionale per formare una gerarchia. Puoi decidere cosa è e non è una funzionalità e controllare le autorizzazioni a livello di codice. Ciò dovrebbe anche consentire di verificare l'accesso a livello di funzionalità prima di disegnare un menu, in modo che gli utenti non vedano mai collegamenti a pagine a cui non sono autorizzati ad accedere.

viene descritta una situazione / soluzione simile qui

Delle tue due proposte, la prima opzione sembra un po 'migliore in quanto ti consente di aggiungere azioni che potrebbero non essere azioni a livello di modello. Suppongo che ti imbatterai in un caso in cui il secondo modello non fa abbastanza, e dovrai cambiare lo schema o iniziare a cospargere la logica delle autorizzazioni in tutta la tua app (es. & Quot; Utenti senza "creare" inoltre l'accesso non può eseguire il metodo xxx ")

Penso che il motivo per cui la soluzione non sembra molto SECCA sia la ripetizione:

  1. Nei nomi dei dipartimenti e
  2. Nelle funzionalità del dipartimento

Per quanto riguarda il n. 1, sarebbe opportuno creare una tabella dei dipartimenti e assegnare a ciascun dipartimento un ID.

Per quanto riguarda il n. 2, sono d'accordo con il primo commento. Probabilmente è possibile raggruppare i vari controller e azioni in gruppi funzionali e quindi impostare una relazione molti-a-molti (tabella di mappatura) tra utenti e funzioni. Le funzioni avrebbero quindi una relazione uno-a-molti con quali azioni / controller consentono. Ciò ti consentirebbe, con la minima ripetizione, di dire cose come "la contabilità e le vendite dovrebbero essere in grado di leggere tutte le tabelle finanziarie". & Quot;

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top