source: trunk/grails-app/controllers/dbnp/authentication/RegisterController.groovy @ 1712

Last change on this file since 1712 was 1712, checked in by robert@…, 9 years ago

Solved user registration bugs: changing password didn't work and lost password form resulted in an error

  • Property svn:keywords set to Rev Author Date
File size: 5.2 KB
Line 
1/* Copyright 2009-2010 the original author or authors.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *      http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15package dbnp.authentication
16
17import groovy.text.SimpleTemplateEngine
18
19import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
20import org.codehaus.groovy.grails.plugins.springsecurity.NullSaltSource
21import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
22
23/**
24 * @author <a href='mailto:burt@burtbeckwith.com'>Burt Beckwith</a>
25 */
26class RegisterController {
27
28        def springSecurityService
29        def mailService
30       
31        static defaultAction = 'index'
32
33        def saltSource
34
35        def index = {
36                [command: new RegisterCommand()]
37        }
38
39        def forgotPassword = {
40
41                if (!request.post) {
42                        // show the form
43                        return
44                }
45
46                String username = params.username
47                if (!username) {
48                        flash.userError = message(code: 'spring.security.ui.forgotPassword.username.missing')
49                        return
50                }
51
52                def user = SecUser.findByUsername(username)
53                if (!user) {
54                        flash.userError = message(code: 'spring.security.ui.forgotPassword.user.notFound')
55                        return
56                }
57
58                def registrationCode = new RegistrationCode(username: user.username, expiryDate: new Date() + 1 )
59                if( !registrationCode.save() ) {
60                        println registrationCode.errors
61                        flash.userError = "Your password could not be reset because of database errors. Please contact the system administrator."
62                        return
63                }
64               
65                String url = generateLink('resetPassword', [t: registrationCode.token])
66
67                def conf = SpringSecurityUtils.securityConfig
68                def body = g.render(template:'/email/passwordReset', model: [user: user, url: url])
69               
70                mailService.sendMail {
71                        to user.email
72                        from conf.ui.forgotPassword.emailFrom
73                        subject conf.ui.forgotPassword.emailSubject
74                        html body.toString()
75                }
76
77                [emailSent: true]
78        }
79
80        def resetPassword = { ResetPasswordCommand command ->
81
82                String token = params.t
83
84                def registrationCode = token ? RegistrationCode.findByToken(token) : null
85                if (!registrationCode) {
86                        flash.userError = message(code: 'spring.security.ui.resetPassword.badCode')
87                        redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
88                        return
89                }
90
91                if (!request.post) {
92                        return [token: token, command: new ResetPasswordCommand()]
93                }
94
95                command.username = registrationCode.username
96                command.validate()
97
98                if (command.hasErrors()) {
99                        return [token: token, command: command]
100                }
101
102                String salt = registrationCode.username
103                RegistrationCode.withTransaction { status ->
104                        def user = SecUser.findByUsername(registrationCode.username)
105                        user.password = springSecurityService.encodePassword(command.password, salt)
106                        user.save()
107                        registrationCode.delete()
108                }
109
110                springSecurityService.reauthenticate registrationCode.username
111
112                flash.message = message(code: 'spring.security.ui.resetPassword.success')
113
114                def conf = SpringSecurityUtils.securityConfig
115                String postResetUrl = conf.ui.register.postResetUrl ?: conf.successHandler.defaultTargetUrl
116                redirect uri: postResetUrl
117        }
118
119        protected String generateLink(String action, linkParams) {
120                createLink(base: "$request.scheme://$request.serverName:$request.serverPort$request.contextPath",
121                                controller: 'register', action: action,
122                                params: linkParams)
123
124        }
125
126        protected String evaluate(s, binding) {
127                new SimpleTemplateEngine().createTemplate(s).make(binding)
128        }
129
130        static final passwordValidator = { String password, command ->
131                if (command.username && command.username.equals(password)) {
132                        return 'command.password.error.username'
133                }
134
135                if (!password || password.length() < 8 || password.length() > 64 ||
136                                (!password.matches('^.*\\p{Alpha}.*$') ||
137                                !password.matches('^.*\\p{Digit}.*$') ||
138                                !password.matches('^.*[!@#$%^&].*$'))) {
139                        return 'command.password.error.strength'
140                }
141        }
142
143        static final password2Validator = { value, command ->
144                if (command.password != command.password2) {
145                        return 'command.password2.error.mismatch'
146                }
147        }
148}
149
150class RegisterCommand {
151
152        String username
153        String email
154        String password
155        String password2
156
157        static constraints = {
158                username blank: false, validator: { value, command ->
159                        if (value) {
160                                def User = AH.application.getDomainClass(
161                                        SpringSecurityUtils.securityConfig.userLookup.userDomainClassName).clazz
162                                if (User.findByUsername(value)) {
163                                        return 'registerCommand.username.unique'
164                                }
165                        }
166                }
167                email blank: false, email: true
168                password blank: false, minSize: 8, maxSize: 64, validator: RegisterController.passwordValidator
169                password2 validator: RegisterController.password2Validator
170        }
171}
172
173class ResetPasswordCommand {
174        String username
175        String password
176        String password2
177
178        static constraints = {
179                password blank: false, minSize: 8, maxSize: 64, validator: RegisterController.passwordValidator
180                password2 validator: RegisterController.password2Validator
181        }
182}
Note: See TracBrowser for help on using the repository browser.