Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import aaf.vhr.switchch.vho.DeprecatedSubject

class LostPasswordController {

static allowedMethods = [emailed: 'POST', validatereset: 'POST']
static allowedMethods = [emailed: 'POST', validatereset: 'POST', obtainsubject: 'GET']

final String CURRENT_USER = "aaf.vhr.LostPasswordController.CURRENT_USER"
final String EMAIL_CODE_SUBJECT ='controllers.aaf.vhr.lostpassword.email.code.subject'
Expand Down Expand Up @@ -42,6 +42,11 @@ class LostPasswordController {

def managedSubjectInstance = ManagedSubject.findWhere(login: params.login)
if (managedSubjectInstance) {

def smsCode = aaf.vhr.crypto.CryptoUtil.randomAlphanumeric(grailsApplication.config.aaf.vhr.passwordreset.reset_code_length)
managedSubjectInstance.resetCodeExternal = smsCode
managedSubjectInstance.save()

lostPasswordService.sendResetEmail(managedSubjectInstance)
}

Expand Down Expand Up @@ -69,13 +74,15 @@ class LostPasswordController {

session.setAttribute(CURRENT_USER, managedSubjectInstance.id)

// If we haven't generated an SMS code already, generate an SMS code and sent it to the user (even if we have already sent one)
def smsCode = aaf.vhr.crypto.CryptoUtil.randomAlphanumeric(grailsApplication.config.aaf.vhr.passwordreset.reset_code_length)
managedSubjectInstance.resetCodeExternal = smsCode
if (!sendResetCodes(managedSubjectInstance)) {
flash.type = 'error'
flash.message = 'controllers.aaf.vhr.lostpassword.mobile.invalid'
redirect action: 'unavailable'
return
}

flash.type = 'info'
flash.message = 'controllers.aaf.vhr.lostpassword.reset.sent.externalcode'
sendResetCodes(managedSubjectInstance)

redirect action: 'reset'
}

Expand All @@ -98,7 +105,12 @@ class LostPasswordController {
flash.type = 'error'
flash.message = 'controllers.aaf.vhr.lostpassword.resend.error'
} else {
sendResetCodes(managedSubjectInstance)
if (!sendResetCodes(managedSubjectInstance)) {
flash.type = 'error'
flash.message = 'controllers.aaf.vhr.lostpassword.mobile.invalid'
redirect action: 'unavailable'
return
}

managedSubjectInstance.lastCodeResend = new Date()
managedSubjectInstance.save()
Expand Down Expand Up @@ -215,14 +227,19 @@ Remote IP: ${request.getRemoteAddr()}"""
true
}

private void sendResetCodes(ManagedSubject managedSubjectInstance) {
// SMS reset code (UI asks to contact admin if no mobile)
if(managedSubjectInstance.mobileNumber) {
if(!sendsms(managedSubjectInstance)) {
redirect action: 'unavailable'
return
}
private boolean sendResetCodes(ManagedSubject managedSubjectInstance) {

if(!managedSubjectInstance.mobileNumber) {
log.error "Cannot send SMS to ${managedSubjectInstance} since they have no mobile number!"
return false;
}

if(!ManagedSubject.validMobileNumber(managedSubjectInstance.mobileNumber, managedSubjectInstance)) {
log.error "Cannot send SMS to ${managedSubjectInstance} since they have an invalid mobile number ${managedSubjectInstance.mobileNumber} !"
return false
}

sendsms(managedSubjectInstance)
}

private boolean sendsms(ManagedSubject managedSubjectInstance) {
Expand Down
17 changes: 12 additions & 5 deletions virtualhome/grails-app/domain/aaf/vhr/ManagedSubject.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -515,13 +515,20 @@ class ManagedSubject {
checkedNumber = "+64$checkedNumber"
}

checkedNumber = checkedNumber.replace(' ','')
// Silently remove anything that might be entered by users in a valid-looking phone number.
checkedNumber = checkedNumber.replaceAll("[- .()]", '')

if(!checkedNumber.startsWith('+')) {
// Valid phone numbers for the app only contain '+' and 0-9. Anything else is probably junk that users will be warned about.
def newNumber = checkedNumber.replaceAll("[^0-9+]", '')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may now be nit-picking, but wondering whether to make diff (and resulting code) smaller by avoiding a new variable and instead of defining newNumber only to be used in one test, you could do:

   if (checkedNumber.replaceAll("[^0-9+]", '') != checkedNumber)

(Or possibly finding a shorter way to check if it contains any characters other than 0-9+)

But this is at code-style level - and also OK to leave as it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newNumber is used later on to assign to the class variable. I think your suggestion means we'd need an extra call like checkedNumber = checkedNumber.replaceAll... later in the code.

if (newNumber != checkedNumber) {
return false
}

if(!newNumber.startsWith('+')) {
return false
} else {
obj.mobileNumber = checkedNumber
return true
}

obj.mobileNumber = newNumber
return true
}
}
1 change: 1 addition & 0 deletions virtualhome/grails-app/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ controllers.aaf.vhr.lostpassword.reset.sent.externalcode=Your password reset cod
controllers.aaf.vhr.lostpassword.reset.sent.email=Your password reset code has been sent via an email. Please allow at least 5 minutes for codes to be delivered.
controllers.aaf.vhr.lostpassword.reset.mobile.missing=You must have a mobile number configured to receive an SMS code. Please contact your administrators for more information.
controllers.aaf.vhr.lostpassword.reset.url.badsecret=An error has occurred while attempting to reset your password. Please try again.
controllers.aaf.vhr.lostpassword.mobile.invalid=A reset code could not be sent to you because of an issue with your configured mobile number. Please contact one of our administrators to address this.

controllers.aaf.vhr.lostusername.email.subject=Your Tuakiri Virtual Home username
controllers.aaf.vhr.lostusername.recaptcha.error=Data supplied for the recaptcha field could not be verified
Expand Down