Forgot Password, Change Password, Reset Password functionality using grails



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: