Tuesday, 22 July 2014

Back to Grails

Got my hands onto Grails coding after nearly a year. I had done a small project using Grails as my spare-time coding but lost the whole thing when I backed it up on a pen drive, went for an OS upgrade and then found that the pen drive was messed up and could not retrieve the stuff.

But Grails is a high-productive framework, so I hope to be quickly back to where I was. One small anecdote from the very first day, though. The initial coding I did was to authenticate the user and then redirect to the home page. The Grails documentation has the steps to setup Spring Security for user authentication. So the way I set it up was --

Application root (/) is mapped to auth.gsp as generated by Spring Security plugin
On successful authentication, user redirect is to /home url which using Grails configuration-over-coding, goes to HomeController, the default action being index method, and since the index method has nothing goes to views/home/index.gsp

But this did not work. Ater scratching my head a few times, because there was no help from any tutorials, I tried a small change as follows:
Application root is mapped to HomeController
HomeController is annotated with @Secured, so the application root takes you to login/auth.gsp
Successful authentication takes you to /home url which is mapped to HomeController, the default action being index method, and since the index method has nothing, user goes to views/home/index.gsp.

This worked!

In summary, this did not work --
"/"(view:'/login/auth')
grails.plugin.springsecurity.successHandler.defaultTargetUrl = '/home'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
---
'/home/**': ['ROLE_USER']
]

but this did --
"/"(controller:'/home')
import grails.plugin.springsecurity.annotation.Secured
@Secured(['ROLE_ADMIN', 'ROLE_USER'])
grails.plugin.springsecurity.successHandler.defaultTargetUrl = '/home'

Update on 23-Jul-2014
Well, I reviewed what I wrote in this post. And it was not clear. To make it clear, here is the use case:
When you start the application, the index page should have login and logout links.
Clicking on login should take to the login page that takes your credentials.
When you click Login button, you should go to your home page.
Home page should have logout link.
Clicking on the logout link should take you back to the index page.
If you directly access the home page, you should get the login page
Given below are the steps, if you follow them it takes just a few minutes to code the above use case for any new app. Lines underlined are files that need to be edited, others are grails commands to be run at command prompt. I have made no changes to the generated UrlMappings.groovy file, I have given below only to show the line that maps application root URL to index page.

grails create-app myproject
cd myproject

grails-app/conf/BuildConfig.groovy
    repositories {
        mavenRepo "http://repo.spring.io/milestone/"
    }

    plugins {

        compile ":spring-security-core:2.0-RC2"
        compile ":spring-security-ui:1.0-RC1"

    }

grails run-app
Ctrl-c
grails s2-quickstart com.mycom.myproject User Role
grails s2ui-override auth

grails-app/conf/BootStrap.groovy
import com.mycom.myproject.Role
import com.mycom.myproject.User
import com.mycom.myproject.UserRole

class BootStrap {

    def init = { servletContext ->
        def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
        def userRole = new Role(authority: 'ROLE_USER').save(flush: true)

        def adminUser = new User(username: 'admin', password: 'admin')
        def mh = new User(username: 'mh', password: 'mh')
        adminUser.save(flush: true)
        mh.save(flush: true)

        UserRole.create adminUser, adminRole, true
        UserRole.create mh, userRole, true

        assert User.count() == 2
        assert Role.count() == 2
        assert UserRole.count() == 2
    }

    def destroy = {
    }
}

grails-app/conf/UrlMappings.groovy
class UrlMappings {

    static mappings = {
    "/$controller/$action?/$id?(.$format)?"{
        constraints {
    // apply constraints here
        }
    }

    "/"(view:"/index")
    "500"(view:'/error')
    }
}

index.gsp
[[Delete all unnecessary content]]
<div>
    <span><a href="/myproject/login/index">Login</a></span>
    <span><a href="/myproject/logout/index">Logout</a></span>
</div>

Config.groovy
grails.plugin.springsecurity.successHandler.defaultTargetUrl = '/home'
grails.plugin.springsecurity.logout.postOnly = false

grails create-controller home

HomeController.groovy
import grails.plugin.springsecurity.annotation.Secured

@Secured(['ROLE_ADMIN', 'ROLE_USER'])

No comments:

Post a Comment