Forgot Password, Change Password, Reset Password functionality using grails
1. Install grails mail plugin. And configure the mail plugin to email reset password link
compile "org.grails.plugins:mail:1.0.7"
2. Create a domain Token.groovy to generate random token to send reset password link to user email
MongoPersistanceListener.groovy>
import java.util.UUID
class Token {
String email
String value = UUID.randomUUID().toString().replaceAll('-', '')
Date dateCreated
static mapping = {
version false
}
static constraints = {
}
}
3. Create a UserService.groovy to send send generate token and send email
class UserService {
def emailService;
void sendResetPasswordEmail(User user){
def token = Token.findByEmail(user.email)
if(!token) {
token = new Token(email: user.email)
token.save(flush: true);
}
emailService.sendResetPasswordEmail(user, token)
}
}
3. Create a EmailService.groovy to send email
import grails.plugin.asyncmail.AsynchronousMailService
import grails.plugin.mail.MailService
class EmailService {
MailService mailService
def groovyPageRenderer
def grailsApplication
/**
* Sends the email to given email id
*/
def sendMail(MailDTO mailDTO) {
log.info "Sending Mail To ==== ${mailDTO?.toMailId}"
mailService.sendMail {
async true
to mailDTO?.toMailId
subject mailDTO.subject
html mailDTO.content
}
}
/*
* Sends the reset password email
*/
def sendResetPasswordEmail(User user, Token token) {
MailDTO mailDTO = new MailDTO()
mailDTO.with {
toMailId = user?.email
subject = "Password reset on Mobile Career Index"
content = groovyPageRenderer.render(template: '/mail/resetPassword', model: [user: user,token:token])
}
sendMail(mailDTO)
}
}
3. Create MailDTO.groovy in src/groovy folder
class MailDTO {
String toMailId
List ccMailIds
String subject
String content
}
3. Create UserController.groovy
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import grails.plugins.springsecurity.Secured
import org.codehaus.groovy.grails.validation.Validateable
class UserController {
def userService
def forgotPassword = {
requireLogout()
if (request.get) {
render view: "/user/forgotPassword"
return;
}
String email = params.email
if (!email) {
flash.error = message(code: 'spring.security.forgotPassword.username.missing')
redirect action: 'forgotPassword'
return
}
def user = User.findByEmail(email);
if (!user) {
flash.error = message(code: 'spring.security.forgotPassword.user.notFound')
redirect action: 'forgotPassword'
return
}
userService.sendResetPasswordEmail(user);
flash.message = message(code: 'spring.security.forgotPassword.sent')
render view: "/user/forgotPassword"
}
@Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
def resetPassword = { ResetPasswordCommand command ->
requireLogout();
flash.message = null;
String tokenValue = params.token
def token = tokenValue ? Token.findByValue(tokenValue) : null
if (!token) {
flash.error = message(code: 'spring.security.resetPassword.badCode')
redirect controller: "home"
return
}
if (request.get) {
render view: "/user/resetPassword" , model:[token: token, command: new ResetPasswordCommand()]
return
}
command.email = token.email
command.validate()
if (command.hasErrors()) {
flash.error = message(code: 'spring.security.resetPassword.badCode')
render view: "/user/resetPassword" , model:[token: token, command: command]
return
}
Token.withTransaction { status ->
def user = User.findByEmail(token.email);
user.password = command.password
user.save(flush: true)
token.delete(flush: true) ;
}
springSecurityService.reauthenticate token.email
flash.message = message(code: 'spring.security.resetPassword.success')
def config = SpringSecurityUtils.securityConfig
redirect uri: config.successHandler.defaultTargetUrl
return
}
@Secured(['IS_AUTHENTICATED_FULLY'])
def editPassword = { EditPasswordCommand command ->
flash.message = null;
if (request.get) {
render view: "/user/editPassword" , model:[command: new EditPasswordCommand()]
return
}
command.validate()
if (command.hasErrors()) {
render view: "/user/editPassword" , model:[command: command]
return
}
User user = springSecurityService.currentUser;
String encodedPassword = springSecurityService.encodePassword(command.currentPassword)
if (encodedPassword != (user.password)) {
flash.error = message(code: 'command.password.error.invalid')
render view: "/user/editPassword" , model:[command: new EditPasswordCommand()]
return;
}
user.password = command.password
user.save(flush: true);
flash.message = message(code: 'spring.security.resetPassword.success')
render view: "/user/editPassword" , model:[command: new EditPasswordCommand()]
}
}
@Validateable
class ResetPasswordCommand {
String email
String password
String password2
static constraints = {
email nullable: false, email: true
password blank: false, nullable: false
password2 validator: password2Validator
}
static final password2Validator = { value, command ->
if (command.password != command.password2) {
return 'command.password2.error.mismatch'
}
}
}
@Validateable
class EditPasswordCommand {
String currentPassword
String password
String password2
static constraints = {
currentPassword blank: false, nullable: false
password blank: false, nullable: false
password2 validator: password2Validator
}
static final password2Validator = { value, command ->
if (command.password != command.password2) {
return 'command.password2.error.mismatch'
}
}
}
I have used parsley.js to validate the forms
Create forgotPassword.gsp in views/user folder
Forgot Password
Reset Password
Submit
Create resetPassword.gsp in views/user folder
Reset Password
Reset Password
Submit
Create editPassword.gsp in views/user folder
Change Password
Change Password
Cancel
Update
Categories:
Groovy & Grails
