Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercepting Grails GSP actions on either client or server side

Grails 2.4.5 here. I am trying to implement the following UX behavior for my GSPs:

  • If a user has permission to click a button, then they may do so; however
  • If the user doesn't have permission to click a button, then when they click the button, a banner message (flash?) appears across the top of the screen with an rose/pinkish/red background stating 'You don't have permission to take this action'

To determine whether the user has the required permission, I have access to functionality from both the Groovy and GSP/taglib layers.

From the Groovy/controller layer:

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

From the GSP/taglib layer:

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

So, given those two available access checking mechanisms, and given the following controller:

class FizzController {
    BuzzService BuzzService

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

...where buzz.gsp is:

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

Given all that, my question is: How/where should I: (1) respond to the 'update' button's click handler, (2) perform the access check, and (3) render the error/banner/flash message? Code example (even pseudo-code) would be most awesome!

like image 657
smeeb Avatar asked Jan 18 '16 10:01

smeeb


2 Answers

Here is what I would suggest:

  1. Make sure your controller method is role based
  2. Remove permission check in GSP, if the button should be visible to everyone
  3. Create an AJAX call upon submission, if the response status is 403, display the banner.
like image 151
Armaiti Avatar answered Nov 17 '22 18:11

Armaiti


If I were you, I'd probably try to use before-action filter in this case. In this filter I'd make a checking if current user has permissions to such an action (checking permissions should always be done in server-side, because of security reasons) and than:

  • if security check passes - just return true (controller will continue it's flow)

  • if security check fails - you can use default flash.message and return false (with propriate css style flasheed message could appears across the top of the screen with an rose/pinkish/red background)

Example code:

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
   }
}

If you want to use filter only to specific controller/action, check applying section. Remember also, that you can use invert rule filter.

More info about different filterTypes.

You should also remember to add flash.message section to your layout (or selected views). You can always specify type of flash message and it's css style.

like image 3
Michal_Szulc Avatar answered Nov 17 '22 19:11

Michal_Szulc