#20 Restricting Access
Limitare gli accessi
Nell’ultimo episodio abbiamo creato i link per creare, modificare e cancellare gli episodi sul sito web ASCIIcasts. I link funzionano, ma un po’ troppo bene, dal momento che possono essere utilizzati da chiunque raggiunga il sito.
La pagina che mostra l’elenco degli episodi con i collegamenti amministrativi visibili per tutti gli utenti.
Quello che vorremmo è di restringere l’accesso a tali link ai soli utenti che hanno i permessi per usarli. Modifichiamo il nostro partial degli episodi in modo tale che mostri i link edit
e destroy
solo se la chiamata a un metodo admin?
restituisce true. (e facciamo lo stesso anche per gli altri link amministrativi, anche se il codice di questi non è riportato qui)
<li> <p class="episodeId"><%= episode.episode_id %></p> <h3><%= link_to episode.title, episode_path(episode.identifier) %></h3> <p class="summary"><%= episode.summary %></p> <p class="tagList"> Tags: <% episode.tags.each do |tag| %><%= link_to tag.title, tag_path(tag.title) %><% end %> </p> <% if admin? %> <p class="adminActions"> <%= link_to "Edit", edit_episode_path(episode) %> <%= link_to "Destroy", episode_path(episode), :confirm => "Are you sure?", :method => :delete %> </p> <% end %> </li>
Il partial dell’episodio con il controllo sulla funzione admin?
che maschera i link edit e destroy.
Abbiamo bisogno di scrivere il metodo admin?
, ma dove deve andare? Dal momento che stiamo richiamando il metodo da una vista, la prima immediata risposta che viene in mente è l’ application helper, ma volendo poter richiamarlo anche dai controller, è meglio metterlo nell’application controller:
class ApplicationController < ActionController::Base helper_method :admin? protected def admin? false end end
Il metodo admin?
aggiunto all’ApplicationController
.
Per ora, il nostro metodo admin?
restituirà semplicemente e sempre false
, (implementeremo correttamente questo metodo nel prossimo episodio). Poichè vogliamo anche usarlo nelle nostre viste, useremo il metodo helper_method
che lo rende il metodo sul controller disponibile anche alle viste.
Quasi arrivati
Ora che abbiamo scritto il nostro metodo admin?
, i nostri link vengono nascosti agli utenti non aministrativi. C’è ancora un problema, tuttavia: chiunque può ancora visitare le pagine amministrative direttamente e aggiungere o modificare gli episodi in questo modo. Possiamo sistemarlo con il before_filter
:
class EpisodesController < ApplicationController before_filter :authorize, :except => [:index, :show ] def index @episodes = Episode.find(:all) end # show, new, create, edit, update and destroy methods hidden. end
Il controller degli episodi (con il corpo dei metodi rimosso).
Il before_filter
di sopra esegue un metodo chiamato authorize
prima di eseguire qualsiasi metodo nel nostro controller, eccetto i metodi index
e show
. Ora abbiamo bisogno di scrivere il metodo authorize
. Lo mettiamo in application controller in modo tale da renderlo disponibile per tutti i controller:
class ApplicationController < ActionController::Base helper_method :admin? protected def admin? false end def authorize unless admin? flash[:error] = “Unauthorized access” redirect_to home_path false end end end
L’ ApplicationController
con l’aggiunta del metodo authorize
.
Il metodo controlla che l’utente sia un amministratore e, se non lo è, mostra un messaggio flash e ridirige alla home page. Infine ritorna false
in modo tale che nessuna ulteriore action venga eseguita. Ora, se proviamo a visitare direttamente la pagina di creazione di un nuovo episodio, verremo rimandati alla home page. In alternativa, se non volessimo nemmeno che l’utente non autorizzato fosse a conoscenza di tale pagina, potremmo lanciare un errore HTTP 404 (Page Not Found).
#DA FARE:
Il nostro sistema di admin è quasi finito, ci manca solo di implementare correttamente il metodo admin?
. Lo faremo nel prossimo episodio.