2016-01-18 24 views
11

Grails 2.4.5 qui. Sto cercando di implementare il seguente comportamento UX per i miei SPG:Intercettazione di azioni GSP Grails sul lato client o server

  • Se un utente ha il permesso di fare clic su un pulsante, può farlo; tuttavia
  • Se l'utente non dispone di l'autorizzazione per fare clic su un pulsante, quindi quando fa clic sul pulsante, viene visualizzato un messaggio banner (flash?) nella parte superiore dello schermo con uno sfondo rosa/rosato/rosso che indica " non hai il permesso di compiere questa azione '

per determinare se l'utente ha il permesso richiesto, ho accesso a funzionalità sia dal Groovy e strati/taglib SPG.

Dallo strato Groovy/regolatore:

SecurityUtils.hasPermission(String permission) 
Ex: SecurityUtils.hasPermission('UPDATE_BUZZ') 

Dallo strato GSP/taglib:

<sec:hasPermission permission="<permission name>">???</sec:hasPermission> 
Ex: <sec:hasPermission permission="UPDATE_BUZZ">???</sec:hasPermission> 

Così, in tali due disponibili meccanismi di controllo di accesso, e dato il seguente controller:

class FizzController { 
    BuzzService BuzzService 

    def buzz() { 
     SomeData dataModel = buzzService.getModel(params) 
     render(view: 'buzz', model: [ dataModel: dataModel ]) 
    } 
} 

... dove buzz.gsp è:

<!-- Lots of HTML/GSP here --> 
<g:submitButton name="update" value="Update" /> 
<!-- Lots more HTML/GSP down here --> 

Considerato tutto questo, la mia domanda è: Come/dove dovrei: (1) rispondere alla 'update' handler clic del pulsante, (2) eseguire il controllo di accesso, e (3) rendere l'errore/messaggio banner/flash? Esempio di codice (anche pseudo-codice) sarebbe davvero fantastico!

risposta

2

Sto assumendo dalla domanda che non si desidera un aggiornamento della pagina e forse nemmeno una chiamata Ajax. Perché se lo facessi, mostrare un banner non è difficile. Vuoi solo che questo si comporti come JavaScript validazione lato client (UX saggio). Se questa ipotesi è sbagliata, allora non leggere e utilizzare la soluzione di Aramiti. Altrimenti vai avanti.

Prima soluzione

È possibile creare un tag che prende un permesso come input.Qualcosa come

<myTagLib:flashOnNoPermission permission="PERM" name="name" value="value"> 
</myTagLib:flashOnNoPermission> 

La definizione di questo tag può controllare l'autorizzazione utilizzando sec:hasPermission. Allora questo tag può solo rendere un modello contenente qualcosa come questo

<hidden flash message> 
<g:submitButton name="name" value="value" onclick="<unhide flash if no permission>"/> 

Fondamentalmente creare un wrapper sopra tasto graal in modo che si può avere messaggi flash alongwith pulsanti.

Problema

  • Cosa se le autorizzazioni dell'utente vengono modificati quando l'utente si trova sullo schermo? Ajax si prende cura di questo, ma questo non lo fa. Una volta caricato lo schermo, tutto è stato risolto.
  • Il banner è alongwith il pulsante

Seconda soluzione

Aggiungi un comune div nella parte superiore del layout per la visualizzazione di messaggi flash. Quindi crea un tag simile al precedente. Basta non aggiungere il messaggio flash nel modello renderizzato. Qualcosa di simile

<g:submitButton name="name" value="value" onclick="<unhide flash at top of layout if no permission>"/> 

Problema

  • Cosa se le autorizzazioni dell'utente vengono modificati quando si trova sullo schermo?

Non sono sicuro del motivo per cui è necessario il gestore onclick, ma se non c'è motivo, la soluzione di Aramiti.

2

Il modo migliore sarebbe nascondere il pulsante se l'utente non ha il permesso di usarlo. Ciò potrebbe facilmente essere ottenuto tramite <sec:hasPermission permission="UPDATE_BUZZ">button</sec:hasPermission>

Se si desidera che il pulsante venga visualizzato anche per l'utente senza autorizzazione, è possibile utilizzare la stessa hasPermission per aggiungere una classe extra al pulsante. Ora acquisisci l'evento clock per quella classe usando jQuery e mostra il tuo messaggio.

+0

Grazie @ashipj (+1) - sì, sfortunatamente ho ancora bisogno di visualizzare il pulsante per l'utente, ** anche ** se non hanno il permesso di fare clic su + eseguirlo. ** Ti dispiacerebbe aggiornare la tua risposta con alcuni esempi di codice/pseudo-codice, in particolare: (1) aggiungere la classe extra al pulsante e (2) catturare l'evento "orologio" per quella classe? ** Io non sono solo comprensione per qualche motivo ... grazie ancora così tanto! – smeeb

3

Ecco quello che vorrei suggerire:

  1. Assicurarsi che il metodo di controllo è basato sul ruolo
  2. Rimuovi controllo Permesso a GSP, se il pulsante dovrebbe essere visibile a tutti
  3. Creare una chiamata AJAX su invio, se lo stato della risposta è 403, visualizzare il banner.
+0

Un commento sarebbe utile per il voto basso. – Armaiti

+1

È la soluzione migliore. I controlli delle autorizzazioni devono essere effettuati sul lato server durante la convalida del modello. Con Grails non è necessario restituire lo stato 403, è possibile restituire solo una stringa di origine del messaggio (anziché JSON) e per il modello di backbone verrà trattato come un errore su save(). Sul lato client, il gatto cattura tutti i 403 e i 500 e usa anche smth come toastr.error (messaggio). Quindi è molto facile passare gli errori di validazione dei grails al servizio lato client. –

+0

Preferisco invece fare il filtraggio. Sembra una soluzione molto più pulita e universale. –

3

Se fossi in te, probabilmente in questo caso proverò ad utilizzare il filtro prima dell'azione. In questo filtro mi piacerebbe fare una verifica se l'utente corrente dispone delle autorizzazioni per una tale azione (permessi controllo dovrebbe sempre essere fatto in lato server, per motivi di sicurezza) e rispetto:

  • se controllo di sicurezza passa - basta restituire true (il controllore continuerà il flusso)

  • se il controllo di sicurezza ha esito negativo - è possibile utilizzare il valore predefinito di flash.message e restituire false (con un messaggio di tipo flasheed in stile css potrebbe apparire nella parte superiore dello schermo con una rosa/rosato/sfondo rosso)

01 Codice

Esempio:

class UserFilters { 
    def filters = { 
     // ... other filters ... 
     permissionAllCheck(controller: '*', action: '*') { 
     before = { 
      doPermissionCheck(delegate) 
     } 
     } 
    } 

    private boolean doPermissionCheck(filters) { 
     if (! YourService.checkForPermissionForCurrentlyLoggedUser()) { 
      filters.flash.message = "You don't have permission to take this action" 
      return false 
     } 
     true 
    } 
} 

Se si desidera utilizzare il filtro solo per specifiche del controller/azione, controllare applying sezione. Ricorda anche che puoi usare invert rule filter.

Ulteriori informazioni su diverso filterTypes.

È inoltre necessario ricordare di aggiungere la sezione flash.message al layout (o alle viste selezionate). Puoi sempre specificare il messaggio type of flash ed è stile css.