Allow e Deny

Approfondimento 8.5

Percentuale Tradotta

In questo capitolo imparerai:

  • Approfondire le callback Allow e Deny.
  • Capire in quale ordine vengono chiamate le callback.
  • Il sistema di sicurezza di Meteor ci permette di controllare le modifiche al database senza dover definire dei Metodi ogni volta che facciamo una modifica.

    Dato che abbiamo bisogno di eseguire operazioni ausiliarie come decorare il post con proprietà aggiuntive a eseguire azioni speciali quando l'URL del post viene pubblicato, ha senso utilizzare uno specifico Metodo post quando creiamo un post.

    D'altra parte non abbiamo bisogno di creare nuovi Metodi per modificare o eliminare i post. Dobbiamo solo controllare che l'utente abbia i permessi per eseguire queste azioni, e ciò avviene facilmente attraverso le callback allow e deny.

    Usare queste callback ci permette di essere più dichiarativi riguardo alle modifiche al database e di poter dire quali tipi di modifiche possono essere effettuate. Il fatto che si integrino con il sistema di account è un bonus aggiuntivo.

    Callback multiple

    Possiamo definire multiple callback allow, l'importante è che almeno una di esse ritorni true per la modifica che sta eseguendo. In questo modo quando Posts.insert viene chiamata in un browser (non importa che sia dall'interfaccia client o dalla console), il server di conseguenza chiamerà ogni insert fino ache non ne trova uno che ritorna true. Se non ne trova, non da permesso all'inserimento e ritorna un errore 403 al client.

    Allo stesso modo, possiamo definire più di una callback deny. Se una qualunque di esse ritorna true, le modifiche vengono cancellate e viene ritornato un errore 403. Questo significa che per rendere effettivo un insert , saranno chiamate una o più callback allow insert e ogni callback deny insert.

    Note: n/e stands for Not Executed
    Note: n/e stands for Not Executed

    In altre parole, Meteor si muove nella lista di callback partendo da quelle di tipo deny, in seguito quelle di tipo allow, eseguendole fino a che una di esse non ritorna true.

    Un esempio pratico di questo schema è quello di avere due callback allow(), una che controlla se un post appartiene all'utente corrente e una seconda che controlla se questo utente ha i diritti di amministrazione. Se l'utente è un amministratore potrà sicuramente modificare ogni post, dato che almeno una delle callback ritornerà true.

    Compensazione dela latenza

    Ricordate che i Metodi che modificano il database (come .update()) hanno compensazione di latenza, proprio come ogni altro Metodo. Per esempio, se provate ad eliminare un post di cui non avete i permessi attraverso la console del browser, vedrete il post sparire brevemente nel momento in cui viene cancellato nella collezione locale, ma poi lo vedrete riapparire quando il server informa che il documento non è stato cancellato.

    Certamente questo comportamento non è un problema quando viene generato dalla console (se gli utenti provano a mettere mano ai dati tramite console, non è certo un vostro problema quello che succede nei loro browser). Tuttavia dovete assicurarvi che non succeda nell'interfaccia utente. Ad esempio dovete fare in modo che un bottoni “Elimina” non siano visibili agli utenti che non hanno i permessi per eliminare.

    Fortunatamente, dato che potete condividere il codice dei permessi tra client e server (ad esempio potete scrivere una funzione in una libreria chiamata canDeletePost(user, post) e metterla nella cartella condivisa /lib), questo non richiede molto codice extra.

    Permessi lato server

    Ricordatevi che il sistema di permessi si applica solo alle modifiche del database inizializzate dal client. Sul server Meteor assume che tutte le operazioni siano permesse.

    Questo significa che se scrivete un Metodo Meteor deletePost lato server che può essere chiamato dal client, ognuno è in grado di cancellare qualsiasi post. Probabilmente non volete che accada a meno che non abbiate verificato i permessi utente all'interno del Metodo.

    Usare “deny” come callback

    Infine, un trucco che potete fare con deny è di usarlo sulle callback “onX”. Per esempio potete ottenere un timestamp lastModified con il seguente codice:

    Posts.deny({
      update: function(userId, doc, fields, modifier) {
        doc.lastModified = +(new Date());
        return false;
      },
      transform: null
    });
    

    Dato che le callback deny vengono eseguite per ogni update che ha successo, sappiamo che queste callback saranno eseguite e opereranno le modifiche in maniera strutturata.

    In realtà questa tecnica è un hack, dato che potreste volere eseguire le modifiche usando un Metodo. Tuttavia è comunque utile saperlo, e in futuro possiamo sperare che diventi disponibile una callback beforeUpdate.