2

I'm trying to build some administrative tools into my user gsp's without building an entire administration controller and pages.

My application has user's and administrators. A user creates an account, the administrator approves the account before the user can perform certain functions. The admin uses the switchUser feature to review the user's account before approving the account.

Instead of writing code where the admin would then have to go back and look up the user, find their record, and then update the account as approved, I just want to add an 'approve' button on one of the user account pages that is only visible to an admin in the switched user role. The issue is the 'approve' action can't be executed by the user's permissions the admin has switched to, otherwise the user could activate their own account.

This is what the gsp looks like:

my.gsp:

<sec:ifSwitched>
    <p><g:link controller='charge' action='activateProfile'>Approve profile</g:link> - This profile will become live in the system.</p>
</sec:ifSwitched>

I'm using @Secured annotations in my controller

what works but doesn't seem right:

@Secured("permitAll() and isAuthenticated()")
def activateProfile() {
   SpringSecurityUtils.isSwitchedUser() {
      //activate the profile
   }
   else {
      //not allowed unless this is a switched user
   }
}

What I'd like to work but doesn't exist because there is no isSwitchedUser() annotation:

@Secured("isAuthenticated() and (hasAnyRole('ROLE_ADMIN', 'ROLE_SWITCHED_USER') or isSwitchedUser())
def activateProfile() {
   //update the database and make this user's profile active
}

And this of course doesn't work because as the switched user, the switched account doesn't have either of these roles, so a page not authorized error occurs:

@Secured("isAuthenticated() and (hasAnyRole('ROLE_ADMIN', 'ROLE_SWITCHED_USER'))
def activateProfile() {
   SpringSecurityUtils.isSwitchedUser() {
      //activate the profile
   }
   else {
      //not allowed unless this is a switched user
   }
}

Am I just stuck with using permitAll and checking in the action for permission? It works and is secure but doesn't feel right.

spock99
  • 1,182
  • 1
  • 10
  • 32

1 Answers1

0

You can do this using one of the following two ways:

Custom PermissionEvaluator

You can use the hasPermission() methods within security annotations and create a custom PermissionEvaluator. Within code this looks like this:

@PreAuthorize("hasPermission(#myObject, 'update')")
public void updateSomething(myObject) {
  ..
}

Inside the PermissionEvaluator implementation you can place the check for the switched user.

Service calls in security annotations

Inside security expressions you can reference beans by prefixing their bean names with @.

For example:

@PreAuthorize("@mySecurityService.isSwitchedUser() or ...")
public void doSomething(myObject) {
  ..
}

More Details: Both methods require a bit of setup. Some time ago I wrote a much more detailed answer about exactly these two methods. You can find it here: Grails custom security evaluator

Community
  • 1
  • 1
micha
  • 47,774
  • 16
  • 73
  • 80