Skip to content

Commit

Permalink
read in user list. Allow password reset with no username validation. …
Browse files Browse the repository at this point in the history
…All we are missing is the e-mail notification
  • Loading branch information
Ben R Alexander committed Aug 26, 2014
1 parent ec56695 commit 29c7037
Show file tree
Hide file tree
Showing 13 changed files with 608 additions and 34 deletions.
69 changes: 61 additions & 8 deletions grails-app/conf/BootStrap.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,85 @@ class BootStrap {
def springSecurityService

def init = { servletContext ->
def samples = [
'ben':[fullName:'ben Alexander', password:'ben', email: "balexand@broadinstitute.org"],
'mary':[fullName:'Mary Carmichael', password:'mary', email: "maryc@broadinstitute.org"],
'fred': [fullName:'Fred Friendly', password:'fred', email: "fred@broadinstitute.org"]];

//
// first handles users
//
def samples = [:] // put users here as a temporary holding location

// read in users from file
if (User.count()) {
println "Users already loaded. Total operational number = ${User.count()}"
} else {
String fileLocation = grailsApplication.mainContext.getResource("/WEB-INF/resources/users.tsv").file.toString()
println "Actively loading users from file = ${fileLocation}"
File file = new File(fileLocation)
int counter = 1
boolean headerLine = true
file.eachLine {
if (headerLine) {
headerLine = false
} else {
List<String> fields = it.split('\t')
if (fields.size() != 5) {
println "Flawed user file. number fields = ${fields.size()}. Aborting..."
assert false
}
LinkedHashMap attributes = [:]
String username = fields[0];
attributes['password'] = "123"
attributes['fullName'] = fields[1]
attributes['nickname'] = fields[2]
attributes['email'] = fields[0]
samples[username] = attributes
}
}
samples['ben'] = [fullName:'Ben Alexander',
password:'ben',
nickname:'ben',
email: "balexand@broadinstitute.org"]
samples['mary'] = [fullName:'Mary Carmichael',
password:'Mary',
nickname:'Mary',
email: "balexand@broadinstitute.org"]
samples['fred'] = [fullName:'Fred friendly',
password:'Fred',
nickname:'Fred',
email: "balexand@broadinstitute.org"]
}

// ['ben':[fullName:'ben Alexander', password:'ben', email: "balexand@broadinstitute.org"],
// 'mary':[fullName:'Mary Carmichael', password:'mary', email: "maryc@broadinstitute.org"],
// 'fred': [fullName:'Fred Friendly', password:'fred', email: "fred@broadinstitute.org"]];

def userRole = Role.findByAuthority('ROLE_USER') ?: new Role (authority: "ROLE_USER").save()
def adminRole = Role.findByAuthority('ROLE_ADMIN') ?: new Role (authority: "ROLE_ADMIN").save()
def systemRole = Role.findByAuthority('ROLE_SYSTEM') ?: new Role (authority: "ROLE_SYSTEM").save()


// now we actually fill up the user domain object
def users = User.list () ?: []
if (!users){
samples.each {username, attributes->
def user = new User (
username: username,
password: attributes.password,
fullName: attributes.fullName,
nickname: attributes.nickname,
email: attributes.email,
hasLoggedIn: false,
enabled: true)
if (user.validate ()) {
println "Creating user ${username}"
println "Creating user ${username}"
user.save(flush: true)
UserRole.create user,userRole
if (username=='ben'){
if ((username=='ben')||
(username=='balexand')||
(username=='flannick')){
UserRole.create user,adminRole
UserRole.create user,systemRole
}
if (username=='mary'){
if ((username=='mary')||
(username=='maryc')){
UserRole.create user,adminRole
}
} else {
Expand Down
1 change: 1 addition & 0 deletions grails-app/conf/BuildConfig.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ grails.project.dependency.resolution = {
compile ':resources:1.2.8'
compile ':rest-client-builder:2.0.3'
compile ":cache:1.0.1"
compile ":mail:1.0.7"
// compile 'org.objenesis:objenesis:1.4'
// compile "cglib:cglib:2.2"

Expand Down
18 changes: 17 additions & 1 deletion grails-app/conf/Config.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,19 @@ environments {
}
}


// email (gmail)
//grails {
// mail {
// host = "smtp.gmail.com"
// port = 465
// username = "t2dportal@gmail.com"
// password = "diaPortal"
// props = ["mail.smtp.auth":"true",
// "mail.smtp.socketFactory.port":"465",
// "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
// "mail.smtp.socketFactory.fallback":"false"]
// }
//}

//security stuff
grails.plugin.springsecurity.securityConfigType = "InterceptUrlMap"
Expand All @@ -137,6 +149,8 @@ grails.plugin.springsecurity.interceptUrlMap = [
'/home/portalHome': ['ROLE_USER'],
'/system/**': ['ROLE_SYSTEM'],
'/admin/resetPassword': ['permitAll'],
'/admin/resetPasswordInteractive/**': ['permitAll'],
'/admin/updatePasswordInteractive/**': ['permitAll'],
'/admin/updatePassword/**': ['permitAll'],
'/admin/**': ['ROLE_ADMIN'],
'/gene/**': ['ROLE_USER'],
Expand All @@ -161,6 +175,8 @@ grails.plugin.springsecurity.rememberMe.key="td2PortalKey"
grails.plugin.springsecurity.rememberMe.persistent=true
grails.plugin.logout.postOnly=false
grails.plugin.springsecurity.apf.storeLastUsername=true
grails.plugin.springsecurity.dao.hideUserNotFoundExceptions=false
grails.plugin.springsecurity.useSecurityEventListener=true
grails.plugin.springsecurity.failureHandler.exceptionMappings = [
'org.springframework.security.authentication.CredentialsExpiredException': '/admin/resetPassword'
]
Expand Down
4 changes: 4 additions & 0 deletions grails-app/conf/spring/resources.groovy
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Place your Spring DSL code here
import dport.mgr.AuthenticationFailedEventListener
import dport.mgr.UsernameNotFoundEventListener
beans = {
authenticationFailedEventListener(AuthenticationFailedEventListener)
usernameNotFoundEventListener(UsernameNotFoundEventListener)
}
60 changes: 36 additions & 24 deletions grails-app/controllers/dport/mgr/AdminController.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,9 @@ class AdminController {
}



def resetPassword = {
String username = session['SPRING_SECURITY_LAST_USERNAME']
render(view: 'newPassword', model: [ username:session['SPRING_SECURITY_LAST_USERNAME']])
render(view: 'newPassword', model: [ username:username])
}

def updatePassword() {
Expand All @@ -114,20 +113,20 @@ class AdminController {
String newPassword2 = params.newPassword2
if (!password || !newPassword || !newPassword2 || newPassword != newPassword2) {
flash.message = 'Please enter your current password and a valid new password'
render view: 'passwordExpired', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
render view: 'newPassword', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
return
}

User user = User.findByUsername(username)
if (!springSecurityService.passwordEncoder.isPasswordValid(user.password, password, null /*salt*/)) {
flash.message = 'Current password is incorrect'
render view: 'passwordExpired', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
render view: 'newPassword', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
return
}

if (springSecurityService.passwordEncoder.isPasswordValid(user.password, newPassword, null /*salt*/)) {
flash.message = 'Please choose a different password from your current one'
render view: 'passwordExpired', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
render view: 'newPassword', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
return
}

Expand All @@ -138,24 +137,37 @@ class AdminController {
redirect controller: 'login', action: 'auth'
}

// defines a new password?
// def springSecurityService
//
// def updateAction() {
// def person = Person.get(params.id)
//
// params.salt = person.salt
// if (person.password != params.password) {
// params.password = springSecurityService.encodePassword(password, salt)
// def salt = … // e.g. randomly generated using some utility method
// params.salt = salt
// }
// person.properties = params
// if (!person.save(flush: true)) {
// render view: 'edit', model: [person: person]
// return
// }
// redirect action: 'show', id: person.id
// }

def resetPasswordInteractive = {
String username = params.id
if (username.endsWith("broadinstitute")) {
username += ".org"
}
render(view: 'resetPassword', model: [ username:username])
}

def updatePasswordInteractive() {
String username = params.username
if (!username) {
flash.message = 'Sorry, you need to provide a username'
redirect controller: 'login', action: 'auth'
return
}
String newPassword = params.newPassword
String newPassword2 = params.newPassword2
if (!newPassword || !newPassword2 || newPassword != newPassword2) {
flash.message = 'Please two matching password records'
render view: 'passwordExpired', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
return
}

User user = User.findByUsername(username)

user.password = newPassword
user.passwordExpired = false
user.save() // if you have password constraints check them here

redirect controller: 'login', action: 'auth'
}

}
6 changes: 6 additions & 0 deletions grails-app/domain/dport/people/User.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ class User {

String username
String password
String email
String fullName = ""
String nickname = ""
boolean hasLoggedIn
boolean enabled = true
boolean accountExpired
boolean accountLocked
Expand All @@ -16,6 +20,8 @@ class User {
static constraints = {
username blank: false, unique: true
password blank: false
fullName blank:true
nickname blank:true
}

static mapping = {
Expand Down
1 change: 1 addition & 0 deletions grails-app/services/dport/SharedToolsService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import grails.transaction.Transactional

@Transactional
class SharedToolsService {
// MailService mailService

/***
* urlEncodedListOfPhenotypes delivers the information in the Phenotype domain object
Expand Down
2 changes: 1 addition & 1 deletion grails-app/views/admin/newPassword.gsp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<label class="control-label col-sm-3" id="id_email">Username:</label>

<div class="col-sm-8">
<span class='form_control' name='j_username' id='username'/>
<span class='form_control' name='j_username' id='username'>${username}</span>
</div>
</div>

Expand Down
75 changes: 75 additions & 0 deletions grails-app/views/admin/resetPassword.gsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<title><g:message code="springSecurity.login.title"/></title>
<meta name="layout" content="core"/>
<r:require modules="core"/>
<r:layoutResources/>

</head>

<body>

<div id="main">

<div class="container">

<g:if test='${flash.message}'>
<div class="alert alert-danger">${flash.message}</div>
</g:if>

<div class="row">
<div class="col-md-8 col-md-offset-2 login-header">
<p>Please enter a new password</p>
</div>
</div>

<div class="row">
<div class="col-md-6 col-md-offset-3">
<g:form action='updatePasswordInteractive' method='POST' id='passwordResetForm' class='form form-horizontal cssform' autocomplete='off'>

<div class="form-group">
<label class="control-label col-sm-3" id="id_email">Username:</label>

<div class="col-sm-8">
<input type='text' class='text_' name='username' id='username' value="${username}" readonly/>
</div>
</div>

<div class="form-group">
<label class="control-label col-sm-3" for="newPassword">New password:</label>

<div class="col-sm-8">
<input type='password' class='text_' name='newPassword' id='newPassword'/>
</div>
</div>

<div class="form-group">
<label class="control-label col-sm-3" for="newPassword2">New password (again):</label>

<div class="col-sm-8">
<input type='password' class='text_' name='newPassword2' id='newPassword2'/>
</div>
</div>

<div style="text-align:center; padding-top: 20px;">
<input class="btn btn-primary btn-lg" type='submit' id="submit"
value='Reset'/>
</div>

</g:form>

</div>
</div>
</div>

</div>
<script type='text/javascript'>
<!--
(function() {
$('#oldPassword').focus();
})();
// -->
</script>
</body>
</html>
11 changes: 11 additions & 0 deletions src/groovy/dport/mgr/AuthenticationFailedEventListener.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dport.mgr
import org.springframework.context.ApplicationListener
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent
/**
* Created by balexand on 8/26/2014.
*/
class AuthenticationFailedEventListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent > {
void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
println "AuthenticationFailedEventListener fired"
}
}
13 changes: 13 additions & 0 deletions src/groovy/dport/mgr/UsernameNotFoundEventListener.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dport.mgr

import org.springframework.context.ApplicationListener
import org.springframework.security.core.userdetails.UsernameNotFoundException

/**
* Created by balexand on 8/26/2014.
*/
class UsernameNotFoundEventListener implements ApplicationListener<UsernameNotFoundException> {
void onApplicationEvent(UsernameNotFoundException event) {
println "UsernameNotFoundEventListener fired"
}
}
Loading

0 comments on commit 29c7037

Please sign in to comment.