Ignore:
Timestamp:
Nov 16, 2010, 2:57:22 PM (10 years ago)
Author:
robert@…
Message:

Added an expiry date to the confirmation email for the user and administrator. See ticket #189

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/authentication/UserRegistrationController.groovy

    r1138 r1144  
    1717
    1818class UserRegistrationController {
     19        static int DAYS_BEFORE_EXPIRY = 3;
     20        static int DAYS_BEFORE_EXPIRY_ADMIN = 365;
     21
    1922    def springSecurityService
    2023        def authenticationService
     
    3033     * for confirmation
    3134     */
    32     def add = {
    33         if( !params.username || !params.email ) {
    34             flash.message = "You must enter a username and provide an email address"
    35             render(view: "index", model: [username: params.username, email: params.email])
    36             return
    37         }
    38 
    39         // Check whether this username already exists
    40         if( SecUser.findByUsername( params.username ) ) {
    41             flash.message = "Username already exists"
    42             render(view: "index", model: [username: params.username, email: params.email])
    43             return
    44         }
     35    def add = { RegisterCommand command ->
     36               
     37                command.validate()
     38
     39                if (command.hasErrors()) {
     40                        def addSendUserLink = false;
     41
     42                        // Check the errors and append a link if needed
     43                        command.errors.allErrors.each {
     44                                if( it.code == "registerCommand.username.notyetconfirmed" ) {
     45                                        addSendUserLink = true;
     46                                }
     47                        }
     48
     49                        flash.message = "";
     50            render(view: "index", model: [username: params.username, email: params.email, command: command, addSendUserLink: addSendUserLink])
     51                        return
     52                }
    4553
    4654        // Generate a random password
     
    4856
    4957        def user = new SecUser(
    50            username: params.username,
     58           username     : params.username,
    5159           email: params.email,
    5260           password: springSecurityService.encodePassword(password, params.username),
     
    6270        flash.message = ""
    6371
    64         // Create links for the user and administrator to click on. These codes are built from
    65         // the username and encrypted password. They do not provide 100% security, since the codes
    66         // could be broken, but it is enough for the confirmation step
    67         def userCode = ( user.username + user.password + 'user' ).encodeAsMD5();
    68         def adminCode = ( user.username + user.password + 'admin' ).encodeAsMD5();
    69         def userLink = createLink( controller: 'userRegistration', action: 'confirmUser', params: [id: user.id, code: userCode], absolute: true )
    70         def adminLink = createLink( controller: 'userRegistration', action: 'confirmAdmin', params: [id: user.id, code: adminCode], absolute: true )
     72                sendUserConfirmationMail( user, password );
     73                sendAdminConfirmationMail( user );
     74
     75        // Give the user a nice welcome page
     76    }
     77
     78        def sendUserConfirmation = {
     79                def user = SecUser.findByUsername( params.username );
     80                if( !user ) {
     81                        flash.message = "No user with this username is found in the database.";
     82            render(view: "index", model: [username: params.username])
     83                }
     84                if( user.userConfirmed ) {
     85                        flash.message = "This user has already been confirmed";
     86            render(view: "index", model: [username: params.username])
     87                }
     88
     89                // Remove old registration codes
     90                RegistrationCode.deleteByUser(user);
     91
     92                // Create a new password
     93        def password = this.generatePassword(8)
     94                user.password = springSecurityService.encodePassword(password, user.username)
     95
     96                // Send a message
     97                sendUserConfirmationMail(user, password);
     98
     99                flash.message = "A new confirmation email has been sent to your registered email address";
     100                render(view: "index", model: [username: params.username])
     101        }
     102
     103        private sendUserConfirmationMail( SecUser user, String password ) {
     104                def userCode = new RegistrationCode(userId: user.id, expiryDate: new Date() + UserRegistrationController.DAYS_BEFORE_EXPIRY).save( flush: true );
     105        def userLink = createLink( controller: 'userRegistration', action: 'confirmUser', params: [code: userCode.token], absolute: true )
    71106
    72107        // Send an email to the user
    73108        try {
    74109            sendMail {
    75                 to      params.email
     110                to      user.email
    76111                subject "Registration at GSCF"
    77                 html    g.render(template:'/email/registrationConfirmationUser', model:[username: user.username, password: password, link: userLink])
     112                html    g.render(template:'/email/registrationConfirmationUser', model:[username: user.username, password: password, expiryDate: userCode.expiryDate, link: userLink])
    78113            }
    79114        } catch(Exception e) {
    80115            log.error "Problem sending email $e.message", e
    81116            flash.message = 'Email could not be sent'
    82         }
     117                        return false
     118        }
     119
     120                return true
     121        }
     122
     123        private sendAdminConfirmationMail( SecUser user ) {
     124                def adminCode = new RegistrationCode(userId: user.id, expiryDate: new Date() + UserRegistrationController.DAYS_BEFORE_EXPIRY_ADMIN).save(flush: true)
     125        def adminLink = createLink( controller: 'userRegistration', action: 'confirmAdmin', params: [code: adminCode.token], absolute: true )
    83126
    84127        // Send an email to the administrators
    85128        try {
     129                        // Determine administrator email addresses
    86130            sendMail {
    87131                to      "gscfproject@gmail.com"
     
    92136            log.error "Problem sending email $e.message", e
    93137            flash.message = "Email could not be sent to administrators"
    94         }
    95 
    96         // Give the user a nice welcome page
    97         [username: user.username, password: password]
    98     }
     138                        return false
     139        }
     140                return true
     141        }
     142
    99143
    100144    def confirmUser = {
    101         def code = params.code
    102         def id = params.id
    103 
    104         def user = SecUser.findById(id)
    105 
    106         def generatedCode = ( user.username + user.password + "user" ).encodeAsMD5()
    107         if( !user || code != generatedCode ) {
     145        def token = params.code
     146
     147                def registrationCode = token ? RegistrationCode.findByToken(token) : null
     148                if (!registrationCode) {
    108149            flash.message = "No user found with given parameters. Please make sure you have copied the URL correctly."
    109150            return
    110         }
     151                }
     152
     153                if (registrationCode.expiryDate.before(new Date())) {
     154            flash.message = "Your registration should have been confirmed within " + UserRegistrationController.DAYS_BEFORE_EXPIRY + " days. This confirmation link has expired. Please register again."
     155            return
     156                }
     157
     158                def user = SecUser.findById(registrationCode.userId)
    111159
    112160        if( user.userConfirmed ) {
     
    117165        user.userConfirmed = true
    118166        user.save(flush: true)
     167
     168                // Remove the registrationCode
     169                registrationCode.delete();
    119170
    120171        if( user.adminConfirmed ) {
     
    127178    @Secured(['ROLE_ADMIN', 'IS_AUTHENTICATED_FULLY'])
    128179    def confirmAdmin = {
    129         def code = params.code
    130         def id = params.id
    131 
    132         def user = SecUser.findById(id)
    133 
    134         def generatedCode = ( user.username + user.password + "admin" ).encodeAsMD5();
    135         if( !user || code != generatedCode ) {
     180
     181        def token = params.code
     182
     183                def registrationCode = token ? RegistrationCode.findByToken(token) : null
     184                if (!registrationCode) {
    136185            flash.message = "No user found with specified code. Please make sure you have copied the URL correctly."
    137             return;
    138         }
     186            return
     187                }
     188
     189                if (registrationCode.expiryDate.before(new Date())) {
     190            flash.message = "You should have approved this registration within " + UserRegistrationController.DAYS_BEFORE_EXPIRY_ADMIN + " days. This confirmation link has expired."
     191            return
     192                }
     193
     194                def user = SecUser.findById(registrationCode.userId)
    139195
    140196        if( user.adminConfirmed ) {
     
    145201        user.adminConfirmed = true
    146202        user.save(flush: true)
     203
     204                // Remove the registrationCode
     205                registrationCode.delete();
    147206
    148207        flash.message = "The registration of " + user.username + " is approved."
     
    213272                }
    214273        }
     274
     275        static final usernameValidator = { value, command ->
     276                def user = SecUser.findByUsername( command.username );
     277                if( user ) {
     278            if( user.enabled ) {
     279                                return "registerCommand.username.unique"
     280                        } else if( user.dateCreated.after( new Date() - DAYS_BEFORE_EXPIRY ) ) {
     281                                return "registerCommand.username.notyetconfirmed"
     282                        } else {
     283                                RegistrationCode.deleteByUser(user);
     284                                user.delete(flush:true);
     285                        }
     286        }
     287        }
     288
    215289}
    216290
     
    231305}
    232306
     307class RegisterCommand {
     308
     309        String username
     310        String email
     311
     312        static constraints = {
     313                email(blank: false, email: true)
     314                username(blank: false, validator: UserRegistrationController.usernameValidator)
     315        }
     316}
Note: See TracChangeset for help on using the changeset viewer.