I have two controllers and each one have a flow. In my menu I have a link to the flows. If I'm in flow #1 and click in the link of the flow #2, Grails will show me the view of the flow #1.
The only way I found to make this transition work was to have a link to an action that redirects to the flow.
class FirstController {
def firstFlow = {
}
def toFirst() {
redirect action: 'first'
}
}
class SecondController {
def secondFlow = {
}
def toSecond() {
redirect action: 'second'
}
}
Going to /first/first shows the view correctly.
Going to /second/second shows the view of first.
Going to /second/toSecond redirects and show the view correctly.
Backing to /first/first shows the view of second
Goingo to /first/toFisrt shows the view correctly.
Is this a expected behavior? Why the flow don't go to the correct view?
EDIT
The menu is created using Platform Core Navigation API.
navigation = {
app {
first(controller: 'first', action: 'first', title: 'nav.exportar')
second(controller: 'second', action: 'second', title: 'nav.importar')
}
}
Links
http://localhost:8080/my-application/first/first?execution=e14s1
http://localhost:8080/my-application/second/second?execution=e14s1
If we want to cease a flow process (like clicking menu), we need to tell webflow end-state.
so the menu link url should include eventId parameter that means end-state.
I don't know navigation api, but g:link example below:
<g:if test="${params.action=='first'}"><%-- we are in first flow. --%>
<g:link event="toSecond">Go to second</g:link>
</g:if>
<g:else><%-- we are not in first flow, normal link. --%>
<g:link controller="second" action="second">Go to second</g:link>
</g:else>
and first controller:
class FirstController {
def firstFlow = {
// view-state
firstViewState {
on('next').to 'nextAction'
on('toSecond').to 'toSecond' // <g:link event='toSecond'> in gsp
}
// end-state
toSecond() {
redirect (controller:'second', action:'second')
}
}
def toFirst() {
redirect action: 'first'
}
}
Related
I am currently upgrading to Grails 4.1. In the past version I had a static mapping in my URL Mappings.groovy as follows:
class UrlMappings {
static mappings = {
name tool: "tool/$controller/$action?/$id?"{
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
}
"/"(controller: "auth", action: "login")
"500"(view:'/error')
"404"(view:'/notFound')
}
}
This was working perfectly in previous Grails versions and when I click on a link to redirect to the url localhost:8000/tool/converters/list, converter would be recognized as the Controller, list would be recognized as the Action and the correct view would be displayed. Now that I have upgraded, when I click on the link, the url that it redirect to is localhost:8080/tool%2Fconverters/list and the error message "This page isn't working" is what is displayed in the view. The "%2F" somehow gets inserted into the url and is causing the page to not display.
I have looked at the Grails 4 documentation and I don't see any indication that the format for static mappings in the URL Mappings has changed. Does anyone have any idea as to why this is happening and how I can fix it?
See the project at https://github.com/jeffbrown/rookycodermapping.
https://github.com/jeffbrown/rookycodermapping/blob/0b7ff27a7fc8c1c1f7b4cf3dc14430ca1cac7be5/grails-app/controllers/rookycodermapping/SchemaController.groovy
package rookycodermapping
class SchemaController {
def show() {
render 'This is being rendered by the show action in SchemaController.'
}
}
https://github.com/jeffbrown/rookycodermapping/blob/0b7ff27a7fc8c1c1f7b4cf3dc14430ca1cac7be5/grails-app/controllers/rookycodermapping/UrlMappings.groovy
package rookycodermapping
class UrlMappings {
static mappings = {
name tool: "/tool/$controller/$action?/$id?" {}
"/"(view:"/index")
"500"(view:'/error')
"404"(view:'/notFound')
}
}
https://github.com/jeffbrown/rookycodermapping/blob/0b7ff27a7fc8c1c1f7b4cf3dc14430ca1cac7be5/grails-app/views/index.gsp#L56-L59
<p>
Click <g:link action="show" controller="schema">here</g:link> to invoke the show action (g:link action="show" controller="schema").
Click <g:link uri="/tool/schema/show">here</g:link> to invoke the show action (g:link uri="/tool/schema/show").
</p>
Both of those links appear to work as expected.
My Grails app uses the Spring Security plugin. Whenever a user successfully logs in I want to:
store something in the session
redirect them to a custom page (depending on their role)
I need to handle logout events similarly, which was pretty straightforward because the plugin provides a bean named logoutSuccessHandler that can be overriden. I was hoping to similarly find a bean named loginSuccessHandler, but no such luck.
I read the page in the plugin's docs about event handling, but neither of the event handling mechanisms appears to give me access to the current request or session.
If you want to do some stuff upon successful login. You can listen to InteractiveAuthenticationSuccessEvent
class AuthenticationSuccessEventListener implements
ApplicationListener<InteractiveAuthenticationSuccessEvent> {
#Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
.......do some stuff here
}
}
And then register AuthenticationSuccessEventListener as a spring bean in resources.groovy
You can do whatever you want here, however you wont be able to do redirect from listener.
Here's another similar question
Add a config parameter:
grails.plugins.springsecurity.successHandler.defaultTargetUrl = '/myLogin/handleSuccessLogin'
Then add your custom login-handling in the action that handles this URL
class MyLoginController {
def springSecurityService
def handleSuccessLogin() {
session.foo = 'bar'
if (springSecurityService.currentUser.username == 'bob') {
redirect action: 'bobLogin'
} else {
redirect action: 'defaultLogin'
}
}
def bobLogin() {
// bob's login handler
}
def defaultLogin() {
// default login handler
}
}
I recently used this in a project for logging in. Its kind of a hack but works for me. I'm using version 1.2.7.3 of the plugin.
def auth() {
def config = SpringSecurityUtils.securityConfig
if (springSecurityService.isLoggedIn()) {
def user = User.get(principal.id)
def roles = user.getAuthorities()
def admin_role = Role.findByAuthority("ROLE_ADMIN")
//this user is not admin
if(!roles.contains(admin_role)){
//perform redirect to appropriate page
}
redirect uri: config.successHandler.defaultTargetUrl
//log.info(getPrincipal().username + "logged in at :"+new Date())
return
}
String view = 'auth'
String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
render view: view, model: [postUrl: postUrl,
rememberMeParameter: config.rememberMe.parameter]
}
For logging out I used a Logout controller, performed some action before redirecting to the logout handler:
class LogoutController {
/**
* Index action. Redirects to the Spring security logout uri.
*/
def index = {
// perform some action here
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl
}
}
I have a grails 2.2.0 application. I have created a global filter and that has some check. if the check fails then it renders a static view file using render view: viewFileName ending the flow else it returns true saying app can continue.
At login action, the action renders a login view calling render view: loginFileName but it displays the viewFileName instead. Note that filter pass has already passed by now and the check in it has passed too.
This issue seems similar to earlier post
Grails "respond" renders the wrong view when launched from .war file
but the difference is that there are two index view files of same name but in different controller but here we have filter rendering a view if some condition passes which gets displayed even if that condition fails.
To makes sure that this is an issue, i removed that render view: viewFileName in filter with render "< div>....< /div >" and then it worked all well i.e. action displayed the right page and not the static page.
I can post more detail if required. I cannot rely on that page that is in string to render as that will not be long term.
Here are the two classes with issue
class MainController {
def login() {
def param = getHeaderParameters()
render view: "login", model: param
}
}
class MainFilters {
private final String mainControllerName = "main"
private final String startPage = "start"
def GrailsConventionGroovyPageLocator groovyPageLocator
def filters = {
all(controller: '*', action: '*') {
before = {
if (AdminUtils.isStart(request)) {
println "rending start page...."
final fileView = "/$mainControllerName/$startPage"
render view: fileView
}
}
}
}
When you render a page and not redirecting it, your action will be called after the before check, if you not return false. For your scenario you don't want your action to be called so you need to return false after that.
def filters = {
all(controller: '*', action: '*') {
before = {
if (AdminUtils.isStart(request)) {
println "rending start page...."
final fileView = "/$mainControllerName/$startPage"
render view: fileView
return false
}
}
}
}
I have a Grails application with Spring Security implemented (CAS). However, after I hit the logout button, I am not logged out. I have the LogoutController, with following code:
class LogoutController {
def index = {
println "IN LOGOUT CONTROLLER TRYING TO LOGOUT"
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
def accessDenied = {
}
}
And in my Config.groovy file, I have:
grails.plugins.springsecurity.logout.afterLogoutUrl = 'https://login.test.com/cas/logout'
The code for my GSP page is
<g:link controller='Logout'>Logout</g:link>
However, when I click the logout button I get redirected, but not fully logged out. Any ideas on what I am doing wrong?
Have you tried call session.invalidate() direct in the controller index method?
class LogoutController {
def index = {
println "IN LOGOUT CONTROLLER TRYING TO LOGOUT"
session.invalidate()
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl
}
}
Cheers
<g:link controller='Logout'>Logout</g:link>
def index = {
logoutProcessService.process(params)
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUr
}
I'm experience some auto redirecting at the page when it first loaded.
These are my codes:
def editUser = {
if(params.account_expired != null )
{
String updateQuery = "UPDATE user SET expired='"+params.account_expired+"'"
def update = sql.executeUpdate(updateQuery)
redirect (action: listUser)
[update:update]
}
else
{
}
}
so what happen is, when the page got loaded, it auto redirect back to listuser page. This is actually an edituser page and I want it to stay there until the user clicks a button. And then redirect to listuser. Any idea guys?
It's common to use POST method to send update, and GET to show form (as it suggested by W3C, and used in Grails by default). So you can use:
def editUser = {
if (request.method == 'GET') {
render(view: 'editUser')
} else if (request.method == 'POST') {
//.... current code
}
}
by default Grails creates POST form, when you're using <g:form tag, but if you're using plain HTML tags, you should specify POST method as:
<form method="POST">
</form>
That's exactly what your code is supposed to do, because you have this executed:
redirect (action: listUser)
If you want it stay in editUser page, you should remove it. Then
[Query1:Query1]
will render editUser.gsp with this parameter passed.