Spring UI RegisterController - No such property - grails

I am using grails 2.3.4 with ":spring-security-ui:1.0-RC1" and ':spring-security-core:2.0-RC2' plugin. I have configured both plugins in the Config.groovy like that:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.SaaSTemplate.auth.Person'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.SaaSTemplate.auth.PersonRole'
grails.plugin.springsecurity.authority.className = 'com.SaaSTemplate.auth.Role'
//**********************************
// Spring Security UI Settings
//**********************************
//password validation of RegisterController.groovy
grails.plugin.springsecurity.ui.password.validationRegex='^.*(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!##$%^&]).*$' //example: 1Test#!!
grails.plugin.springsecurity.ui.password.minLength=8
grails.plugin.springsecurity.ui.password.maxLength=64
My RegisterController.groovy looks like that:
#Secured(['permitAll'])
class RegisterController extends grails.plugin.springsecurity.ui.RegisterController {
// override default value from base class
static defaultAction = 'index'
// override default value from base class
static allowedMethods = [register: 'POST']
def mailService
def messageSource
def saltSource
def index() {
def copy = [:] + (flash.chainedParams ?: [:])
copy.remove 'controller'
copy.remove 'action'
[command: new RegisterCommand(copy)] // here is where I get the exception!!!!
}
def register(RegisterCommand command) {
if (command.hasErrors()) {
render view: 'index', model: [command: command]
return
}
String salt = saltSource instanceof NullSaltSource ? null : command.username
def user = lookupUserClass().newInstance(email: command.email, username: command.username,
accountLocked: true, enabled: true)
RegistrationCode registrationCode = springSecurityUiService.register(user, command.password, salt)
if (registrationCode == null || registrationCode.hasErrors()) {
// null means problem creating the user
flash.error = message(code: 'spring.security.ui.register.miscError')
flash.chainedParams = params
redirect action: 'index'
return
}
String url = generateLink('verifyRegistration', [t: registrationCode.token])
def conf = SpringSecurityUtils.securityConfig
def body = conf.ui.register.emailBody
if (body.contains('$')) {
body = evaluate(body, [user: user, url: url])
}
mailService.sendMail {
to command.email
from conf.ui.register.emailFrom
subject conf.ui.register.emailSubject
html body.toString()
}
render view: 'index', model: [emailSent: true]
}
def verifyRegistration() {
def conf = SpringSecurityUtils.securityConfig
String defaultTargetUrl = conf.successHandler.defaultTargetUrl
String token = params.t
def registrationCode = token ? RegistrationCode.findByToken(token) : null
if (!registrationCode) {
flash.error = message(code: 'spring.security.ui.register.badCode')
redirect uri: defaultTargetUrl
return
}
def user
// TODO to ui service
RegistrationCode.withTransaction { status ->
String usernameFieldName = SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName
user = lookupUserClass().findWhere((usernameFieldName): registrationCode.username)
if (!user) {
return
}
user.accountLocked = false
user.save(flush:true)
def UserRole = lookupUserRoleClass()
def Role = lookupRoleClass()
for (roleName in conf.ui.register.defaultRoleNames) {
UserRole.create user, Role.findByAuthority(roleName)
}
registrationCode.delete()
}
if (!user) {
flash.error = message(code: 'spring.security.ui.register.badCode')
redirect uri: defaultTargetUrl
return
}
springSecurityService.reauthenticate user.username
flash.message = message(code: 'spring.security.ui.register.complete')
redirect uri: conf.ui.register.postRegisterUrl ?: defaultTargetUrl
}
def forgotPassword() {
if (!request.post) {
// show the form
return
}
String username = params.username
if (!username) {
flash.error = message(code: 'spring.security.ui.forgotPassword.username.missing')
redirect action: 'forgotPassword'
return
}
String usernameFieldName = SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName
def user = lookupUserClass().findWhere((usernameFieldName): username)
if (!user) {
flash.error = message(code: 'spring.security.ui.forgotPassword.user.notFound')
redirect action: 'forgotPassword'
return
}
def registrationCode = new RegistrationCode(username: user."$usernameFieldName")
registrationCode.save(flush: true)
String url = generateLink('resetPassword', [t: registrationCode.token])
def conf = SpringSecurityUtils.securityConfig
def body = conf.ui.forgotPassword.emailBody
if (body.contains('$')) {
body = evaluate(body, [user: user, url: url])
}
mailService.sendMail {
to user.email
from conf.ui.forgotPassword.emailFrom
subject conf.ui.forgotPassword.emailSubject
html body.toString()
}
[emailSent: true]
}
def resetPassword(ResetPasswordCommand command) {
String token = params.t
def registrationCode = token ? RegistrationCode.findByToken(token) : null
if (!registrationCode) {
flash.error = message(code: 'spring.security.ui.resetPassword.badCode')
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
return
}
if (!request.post) {
return [token: token, command: new ResetPasswordCommand()]
}
command.username = registrationCode.username
command.validate()
if (command.hasErrors()) {
return [token: token, command: command]
}
String salt = saltSource instanceof NullSaltSource ? null : registrationCode.username
RegistrationCode.withTransaction { status ->
String usernameFieldName = SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName
def user = lookupUserClass().findWhere((usernameFieldName): registrationCode.username)
user.password = springSecurityUiService.encodePassword(command.password, salt)
user.save()
registrationCode.delete()
}
springSecurityService.reauthenticate registrationCode.username
flash.message = message(code: 'spring.security.ui.resetPassword.success')
def conf = SpringSecurityUtils.securityConfig
String postResetUrl = conf.ui.register.postResetUrl ?: conf.successHandler.defaultTargetUrl
redirect uri: postResetUrl
}
protected String generateLink(String action, linkParams) {
createLink(base: "$request.scheme://$request.serverName:$request.serverPort$request.contextPath",
controller: 'register', action: action,
params: linkParams)
}
protected String evaluate(s, binding) {
new SimpleTemplateEngine().createTemplate(s).make(binding)
}
// static final passwordValidator = { String password, command ->
// if (command.username && command.username.equals(password)) {
// return 'command.password.error.username'
// }
//
// if (!checkPasswordMinLength(password, command) ||
// !checkPasswordMaxLength(password, command) ||
// !checkPasswordRegex(password, command)) {
// return 'command.password.error.strength'
// }
// }
static boolean checkPasswordMinLength(String password, command) {
def conf = SpringSecurityUtils.securityConfig
int minLength = conf.ui.password.minLength instanceof Number ? conf.ui.password.minLength : 8
password && password.length() >= minLength
}
static boolean checkPasswordMaxLength(String password, command) {
def conf = SpringSecurityUtils.securityConfig
int maxLength = conf.ui.password.maxLength instanceof Number ? conf.ui.password.maxLength : 64
password && password.length() <= maxLength
}
static boolean checkPasswordRegex(String password, command) {
def conf = SpringSecurityUtils.securityConfig
String passValidationRegex = conf.ui.password.validationRegex ?:
'^.*(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!##$%^&]).*$'
password && password.matches(passValidationRegex)
}
// static final password2Validator = { value, command ->
// if (command.password != command.password2) {
// return 'command.password2.error.mismatch'
// }
// }
}
class RegisterCommand {
String username
String email
String password
String password2
def grailsApplication
static constraints = {
username blank: false, validator: { value, command ->
if (value) {
def User = command.grailsApplication.getDomainClass(
SpringSecurityUtils.securityConfig.userLookup.userDomainClassName).clazz
if (User.findByUsername(value)) {
return 'registerCommand.username.unique'
}
}
}
email blank: false, email: true
password blank: false, validator: RegisterController.passwordValidator
password2 validator: RegisterController.password2Validator
}
}
class ResetPasswordCommand {
String username
String password
String password2
static constraints = {
password blank: false, validator: RegisterController.passwordValidator
password2 validator: RegisterController.password2Validator
}
}
As you can see I have just copied the original controller from the source code. Therefore the other classes ResetPasswordCommand and RegisterCommand are also included. However, I still get the exception:
ui.SpringSecurityUiService problem creating Person: com.TestApp.auth.Person : (unsaved)
Die Eigenschaft [firstName] des Typs [class com.TestApp.auth.Person] darf nicht null sein
Die Eigenschaft [lastName] des Typs [class com.TestApp.auth.Person] darf nicht null sein
errors.GrailsExceptionResolver MissingPropertyException occurred when processing request: [GET] /TestApp/register/index
No such property: format for class: TestApp.Register.RegisterCommand. Stacktrace follows:
groovy.lang.MissingPropertyException: No such property: format for class: TestApp.Register.RegisterCommand
at TestApp.Register.RegisterController.index(RegisterController.groovy:26)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:200)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.java:53)
at grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:49)
at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Why do I get this exception? I have included the class RegisterCommand (as also in the original source) in my file?
I really appreciate your input!
UPDATE
I changed my method like that:
def index() {
def copy = [:] + (flash.chainedParams ?: [:])
copy.remove 'controller'
copy.remove 'action'
['controller', 'action', 'format'].each { copy.remove it }
[command: new RegisterCommand(copy)]
}
However, now I still cannot process the registration, I get:
....ui.SpringSecurityUiService problem creating Person: com.TestApp.auth.Person : (unsaved)
The property [firstName] of the type [class com.TestApp.auth.Person] cannot be null
The property [lastName] of the type [class com.TestApp.auth.Person] cannot be null

format is added in the UrlMapping as an optional field.
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
So you would end up removing that from the map as done for action and controller.
//index action
['controller', 'action', 'format'].each { copy.remove it }
Another option will be to explicitly use bindData to avoid this collision
//index action
RegisterCommand cmd = new RegisterCommand()
bindData copy, cmd

Related

class Authority is not a domain class or GORM has not been initialized correctly or has already been shutdown

I'm working on a grails rest app. The grails version I'm using is 3.3.1. I'm using spring-security-rest for authorization. I've created the following classes using the s2-quickstart command.
User
Authority
UserAuthority
The app runs fine but the unit tests for the User class fail with the following error in console.
java.lang.IllegalStateException: Either class [hungr.Authority] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
at org.grails.datastore.gorm.GormEnhancer.stateException(GormEnhancer.groovy:469)
at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy:300)
at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy:296)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.currentGormStaticApi(GormEntity.groovy:1349)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.staticMethodMissing(GormEntity.groovy:756)
at hungr.UserController.$tt__save(UserController.groovy:39)
at hungr.UserController.save_closure1(UserController.groovy)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:430)
at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
at org.grails.testing.runtime.support.ActionSettingMethodHandler.invoke(ActionSettingMethodHandler.groovy:28)
at hungr.UserControllerSpec.Test the save action correctly persists(UserControllerSpec.groovy:90)
I've tried referring to the answer at GORM fails to realize Domain classes from a plugin are GORM classes
but nothing worked. I'm pretty new to grails hence I have no clue what may be going wrong.
the classes I'm using are:
User.Groovy
#GrailsCompileStatic
#EqualsAndHashCode(includes='username')
#ToString(includes='username', includeNames=true, includePackage=false)
class User implements Serializable, UserDetails {
private static final long serialVersionUID = 1
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
String name
String email
Integer age
Boolean isVeg
byte[] profilePicture
String profilePictureContentType
String facebookId
String facebookProfilePictureUrl
boolean isFacebookUser
static hasMany = [notifications: Notification, posts: DiaryItem, comments: Comment]
Set<Authority> getAuthorities() {
(UserAuthority.findAllByUser(this) as List<UserAuthority>)*.authority as Set<Authority>
}
#Override
boolean isAccountNonExpired() {
return !accountExpired
}
#Override
boolean isAccountNonLocked() {
return !accountLocked
}
#Override
boolean isCredentialsNonExpired() {
return !passwordExpired
}
static constraints = {
password nullable: false, blank: false, password: true
username nullable: false, blank: false, unique: true
facebookId nullable: true
name nullable: false, blank: false, maxSize: 100
email blank: false, email: true
age nullable: false, min: 8
isVeg nullable: false
profilePicture nullable: true, maxSize: 1073741824
profilePictureContentType nullable: true
isFacebookUser nullable: false
facebookProfilePictureUrl nullable: true, maxSize: 1000
}
static mapping = {
password column: '`password`'
}
}
Authority.Groovy
#GrailsCompileStatic
#EqualsAndHashCode(includes='authority')
#ToString(includes='authority', includeNames=true, includePackage=false)
class Authority implements Serializable, GrantedAuthority {
private static final long serialVersionUID = 1
String authority
static constraints = {
authority nullable: false, blank: false, unique: true
}
static mapping = {
cache true
}
}
UserAuthority.Groovy
#GrailsCompileStatic
#ToString(cache=true, includeNames=true, includePackage=false)
class UserAuthority implements Serializable {
private static final long serialVersionUID = 1
User user
Authority authority
#Override
boolean equals(other) {
if (other instanceof UserAuthority) {
other.userId == user?.id && other.authorityId == authority?.id
}
}
#Override
int hashCode() {
int hashCode = HashCodeHelper.initHash()
if (user) {
hashCode = HashCodeHelper.updateHash(hashCode, user.id)
}
if (authority) {
hashCode = HashCodeHelper.updateHash(hashCode, authority.id)
}
hashCode
}
static UserAuthority get(long userId, long authorityId) {
criteriaFor(userId, authorityId).get()
}
static boolean exists(long userId, long authorityId) {
criteriaFor(userId, authorityId).count()
}
private static DetachedCriteria criteriaFor(long userId, long authorityId) {
UserAuthority.where {
user == User.load(userId) &&
authority == Authority.load(authorityId)
}
}
static UserAuthority create(User user, Authority authority, boolean flush = false) {
def instance = new UserAuthority(user: user, authority: authority)
instance.save(flush: flush)
instance
}
static boolean remove(User u, Authority r) {
if (u != null && r != null) {
UserAuthority.where { user == u && authority == r }.deleteAll()
}
}
static int removeAll(User u) {
u == null ? 0 : UserAuthority.where { user == u }.deleteAll() as int
}
static int removeAll(Authority r) {
r == null ? 0 : UserAuthority.where { authority == r }.deleteAll() as int
}
static constraints = {
user nullable: false
authority nullable: false, validator: { Authority r, UserAuthority ur ->
if (ur.user?.id) {
if (UserAuthority.exists(ur.user.id, r.id)) {
return ['userRole.exists']
}
}
}
}
static mapping = {
id composite: ['user', 'authority']
version false
}
}
EDIT 1:
The Unit Test class is:
class UserControllerSpec extends Specification implements
ControllerUnitTest<UserController>, DomainUnitTest<User> {
def populateValidParams(params) {
assert params != null
// TODO: Populate valid properties like...
//params["name"] = 'someValidName'
params["username"]
params["password"]
params["name"] = "User"
params["email"] = "user#hungr.com"
params["age"] = 19
params["isVeg"] = false
// new MockMultipartFile('profilePicture', 'myImage.jpg', imgContentType, imgContentBytes)
// def multipartFile = new GrailsMockMultipartFile('profilePicture', 'profilePicture.jpg', 'image/jpeg', new byte[0])
//request.addFile(multipartFile)
// params["profilePicture"] =// new MockMultipartFile('profilePicture', 'file.jpg', 'image/jpeg', "1234567" as byte[])
params["profilePictureContentType"] = "image/jpeg"
params["facebookId"] = "fb_id"
params["facebookProfilePictureUrl"] = "http://abc.def"
params["isFacebookUser"] = true
//assert false, "TODO: Provide a populateValidParams() implementation for this generated test suite"
}
void "Test the index action returns the correct model"() {
given:
controller.userService = Mock(UserService) {
1 * list(_) >> []
1 * count() >> 0
}
when:"The index action is executed"
controller.index()
then:"The model is correct"
!model.userList
model.userCount == 0
}
void "Test the create action returns the correct model"() {
when:"The create action is executed"
controller.create()
then:"The model is correctly created"
model.user!= null
}
void "Test the save action with a null instance"() {
when:"Save is called for a domain instance that doesn't exist"
request.contentType = FORM_CONTENT_TYPE
request.method = 'POST'
request.format = 'form'
controller.save(null)
then:"A 404 error is returned"
response.redirectedUrl == '/user/index'
flash.message != null
}
void "Test the save action correctly persists"() {
given:
controller.userService = Mock(UserService) {
1 * save(_ as User)
}
when:"The save action is executed with a valid instance"
response.reset()
request.contentType = FORM_CONTENT_TYPE
request.method = 'POST'
request.format = 'form'
byte[] b = new byte[1]
b[0]= 123
request.addFile(new MockMultipartFile('profilePicture', 'file.jpg', 'image/jpeg', b))
populateValidParams(params)
def user = new User(params)
user.id = 1
controller.save(user)
then:"A redirect is issued to the show action"
response.redirectedUrl == '/user/show/1'
controller.flash.message != null
}
void "Test the save action with an invalid instance"() {
given:
controller.userService = Mock(UserService) {
1 * save(_ as User) >> { User user ->
throw new ValidationException("Invalid instance", user.errors)
}
}
when:"The save action is executed with an invalid instance"
request.contentType = FORM_CONTENT_TYPE
request.method = 'POST'
def user = new User()
controller.save(user)
then:"The create view is rendered again with the correct model"
model.user != null
view == 'create'
}
void "Test the show action with a null id"() {
given:
controller.userService = Mock(UserService) {
1 * get(null) >> null
}
when:"The show action is executed with a null domain"
controller.show(null)
then:"A 404 error is returned"
response.status == 404
}
void "Test the show action with a valid id"() {
given:
controller.userService = Mock(UserService) {
1 * get(2) >> new User()
}
when:"A domain instance is passed to the show action"
controller.show(2)
then:"A model is populated containing the domain instance"
model.user instanceof User
}
void "Test the edit action with a null id"() {
given:
controller.userService = Mock(UserService) {
1 * get(null) >> null
}
when:"The show action is executed with a null domain"
controller.edit(null)
then:"A 404 error is returned"
response.status == 404
}
void "Test the edit action with a valid id"() {
given:
controller.userService = Mock(UserService) {
1 * get(2) >> new User()
}
when:"A domain instance is passed to the show action"
controller.edit(2)
then:"A model is populated containing the domain instance"
model.user instanceof User
}
void "Test the update action with a null instance"() {
when:"Save is called for a domain instance that doesn't exist"
request.contentType = FORM_CONTENT_TYPE
request.method = 'PUT'
controller.update(null)
then:"A 404 error is returned"
response.redirectedUrl == '/user/index'
flash.message != null
}
void "Test the update action correctly persists"() {
given:
controller.userService = Mock(UserService) {
1 * save(_ as User)
}
when:"The save action is executed with a valid instance"
response.reset()
request.contentType = FORM_CONTENT_TYPE
request.method = 'PUT'
request.format = 'form'
request.addFile(new MockMultipartFile('profilePicture', 'file.jpg', 'image/jpeg', "1234567" as byte[]))
populateValidParams(params)
def user = new User(params)
user.id = 1
controller.update(user)
then:"A redirect is issued to the show action"
response.redirectedUrl == '/user/show/1'
controller.flash.message != null
}
void "Test the update action with an invalid instance"() {
given:
controller.userService = Mock(UserService) {
1 * save(_ as User) >> { User user ->
throw new ValidationException("Invalid instance", user.errors)
}
}
when:"The save action is executed with an invalid instance"
request.contentType = FORM_CONTENT_TYPE
request.method = 'PUT'
controller.update(new User())
then:"The edit view is rendered again with the correct model"
model.user != null
view == 'edit'
}
void "Test the delete action with a null instance"() {
when:"The delete action is called for a null instance"
request.contentType = FORM_CONTENT_TYPE
request.method = 'DELETE'
controller.delete(null)
then:"A 404 is returned"
response.redirectedUrl == '/user/index'
flash.message != null
}
void "Test the delete action with an instance"() {
given:
controller.userService = Mock(UserService) {
1 * delete(2)
}
when:"The domain instance is passed to the delete action"
request.contentType = FORM_CONTENT_TYPE
request.method = 'DELETE'
controller.delete(2)
then:"The user is redirected to index"
response.redirectedUrl == '/user/index'
flash.message != null
}
}
So normally in a Unit test you test a single unit, User in this case. Because you want to test additional entities, you need to add them to the test. You can do this by implementing getDomainClassesToMock. Best is to use the DataTest trait instead of the DomainUnitTest in this situation (DomainUnitTest extends DataTest).
So your test should look like:
class UserControllerSpec extends Specification implements
ControllerUnitTest<UserController>, DataTest {
Class<?>[] getDomainClassesToMock(){
return [User,Authority,UserAuthority] as Class[]
}
....
}

Null Pointer Exception using PlainUsername

When I Edit the user all are saving but when I change the password it is getting the error.Please help me.
NullPointerException occurred when processing request: [POST] /openbrm /user/save
Stacktrace follows:
java.lang.NullPointerException
at com.sapienter.jbilling.client.authentication.CompanyUserDetails.getPlainUsername(CompanyUserDetails.java:84)
at com.sapienter.jbilling.client.authentication.JBillingPasswordEncoder.isPasswordValid(JBillingPasswordEncoder.java:75)
at com.sapienter.jbilling.client.user.UserHelper.bindPassword(UserHelper.groovy:155)
at jbilling.UserController.save(UserController.groovy:304)
at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.java:53)
at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
UserController.groovy
def save () {
UserWS user = new UserWS()
user.mainRoleId= Constants.TYPE_ROOT
UserHelper.bindUser(user, params)
def contacts = []
def userId= params['user']['userId'] as Integer
log.debug "Save called for user ${userId}"
def oldUser = userId ? webServicesSession.getUserWS(userId) : null
def company_id = session['company_id']
def company = CompanyDTO.createCriteria().get {
eq("id", company_id)
fetchMode('contactFieldTypes', FM.JOIN)
}
if ( !oldUser || SpringSecurityUtils.ifAllGranted('ROLE_SUPER_USER') || SpringSecurityUtils.ifAllGranted('MY_ACCOUNT_162') ) {
UserHelper.bindUser(user, params)
UserHelper.bindContacts(user, contacts, company, params)
} else {
user= oldUser
contacts= userId ? webServicesSession.getUserContactsWS(userId) : null
}
if ( !oldUser || SpringSecurityUtils.ifAllGranted('ROLE_SUPER_USER') || SpringSecurityUtils.ifAllGranted('MY_ACCOUNT_161') ) {
UserHelper.bindPassword(user, oldUser, params, flash)
} else {
user.password= null
}
UserDTO loggedInUser = UserDTO.get(springSecurityService.principal.id)
if (flash.error) {
user = new UserWS()
UserHelper.bindUser(user, params)
contacts = []
UserHelper.bindContacts(user, contacts, company, params)
render view: 'edit', model: [user: user, contacts: contacts, company: company, loggedInUser: loggedInUser, roles: loadRoles()]
return
}
try {
if (!oldUser) {
log.debug("creating user ${user}")
user.userId = webServicesSession.createUser(user)
flash.message = 'user.created'
flash.args = [user.userId as String]
} else {
log.debug("saving changes to user ${user.userId}")
webServicesSession.updateUser(user)
flash.message = 'user.updated'
flash.args = [user.userId as String]
}
// save secondary contacts
if (user.userId) {
contacts.each {
webServicesSession.updateUserContact(user.userId, it);
}
}
} catch (SessionInternalError e) {
flash.clear()
viewUtils.resolveException(flash, session.locale, e)
contacts = userId ? webServicesSession.getUserContactsWS(userId) : null
if(!contacts && !userId){
contacts = [user.getContact()]
}
render view: 'edit', model: [user: user, contacts: contacts, company: company, loggedInUser: loggedInUser, roles: loadRoles()]
return
}
if ( SpringSecurityUtils.ifAnyGranted("MENU_99") || SpringSecurityUtils.ifAnyGranted("ROLE_SUPER_USER") ) {
chain action: 'list', params: [id: user.userId]
} else {
chain action: 'edit', params: [id: user.userId]
}
}
In UserHelper.groovy it is getting the error at this method
static def bindPassword(UserWS newUser, UserWS oldUser, GrailsParameterMap params, flash) {
if (oldUser) {
// validate that the entered confirmation password matches the users existing password
if (params.newPassword) {
//read old password directly from DB. API does not reveal password hashes
def oldPassword = UserDTO.get(oldUser.userId).password
PasswordEncoder passwordEncoder = Context.getBean(Context.Name.PASSWORD_ENCODER)
//fake user details so we can verify the customers password
//should we move this to the server side validation?
CompanyUserDetails userDetails = new CompanyUserDetails(
oldUser.getUserName(), oldPassword, true, true, true, true,
Collections.EMPTY_LIST, null,null,oldUser.getUserId(), oldUser.getMainRoleId(), oldUser.getEntityId(),
oldUser.getCurrencyId(), oldUser.getLanguageId()
)
if (!passwordEncoder.isPasswordValid(oldPassword, params.oldPassword, userDetails)) {
flash.error = 'current.password.doesnt.match.existing'
return
}
} else {
newUser.setPassword(null)
}
}
// verify passwords only when new password is present
if (params.newPassword) {
if (params.newPassword == params.verifiedPassword) {
if (params.newPassword)
newUser.setPassword(params.newPassword)
} else {
flash.error = 'passwords.dont.match'
}
} else {
newUser.setPassword(null)
}
}
My CompanayUserDetails.java
package com.sapienter.jbilling.client.authentication;
import com.sapienter.jbilling.server.user.db.UserDTO;
import org.springframework.security.core.GrantedAuthority;
import grails.plugin.springsecurity.userdetails.GrailsUser;
import java.util.Collection;
import java.util.Locale;
public class CompanyUserDetails extends GrailsUser {
private final UserDTO user;
private final Locale locale;
private final Integer mainRoleId;
private final Integer companyId;
private final Integer currencyId;
private final Integer languageId;
public CompanyUserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<GrantedAuthority> authorities,
UserDTO user, Locale locale,
Integer id, Integer mainRoleId, Integer companyId, Integer currencyId, Integer languageId) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities, id);
this.user = user;
this.locale = locale;
this.mainRoleId = mainRoleId;
this.companyId = companyId;
this.currencyId = currencyId;
this.languageId = languageId;
}
public UserDTO getUser() {
return user;
}
public String getPlainUsername() {
return user.getUserName();
}
public Locale getLocale() {
return locale;
}
public Integer getMainRoleId() {
return mainRoleId;
}
public Integer getUserId() {
return (Integer) getId();
}
public Integer getCompanyId() {
return companyId;
}
public Integer getCurrencyId() {
return currencyId;
}
public Integer getLanguageId() {
return languageId;
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("CompanyUserDetails");
sb.append("{id=").append(getId());
sb.append(", username=").append("'").append(getUsername()).append("'");
sb.append(", mainRoleId=").append(getMainRoleId());
sb.append(", companyId=").append(getCompanyId());
sb.append(", currencyId=").append(getCurrencyId());
sb.append(", languageId=").append(getLanguageId());
sb.append(", enabled=").append(isEnabled());
sb.append(", accountExpired=").append(!isAccountNonExpired());
sb.append(", credentialsExpired=").append(!isCredentialsNonExpired());
sb.append(", accountLocked=").append(!isAccountNonLocked());
sb.append('}');
return sb.toString();
}
}
Well you are passing null into the constructor for UserDTO
see
for
Collection<GrantedAuthority> authorities, UserDTO user, Locale locale,
you are passing
Collections.EMPTY_LIST, null,null
so of course getPlainUsername will fail
In your call to new CompanyUserDetails
CompanyUserDetails userDetails = new CompanyUserDetails(
oldUser.getUserName(), oldPassword, true, true, true, true,
Collections.EMPTY_LIST, null, <--- param $8 is null
And the definition
public CompanyUserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<GrantedAuthority> authorities,
UserDTO user, <--- param #8
And finally the NPE In your call to getPlainUsername
return user.getUserName();
NPE, can not invoke method on null user object.
So to understand your problem you really need to understand error codes:
java.lang.NullPointerException
at com.sapienter.jbilling.client.authentication.CompanyUserDetails.getPlainUsername(CompanyUserDetails.java:84)
According to my editor line 84 was
sb.append(", languageId=").append(getLanguageId());
I would suggest as a test set all these to a value
private final Integer mainRoleId=0;
private final Integer companyId=0;
private final Integer currencyId=0;
private final Integer languageId=0;
then change
this.mainRoleId = mainRoleId;
this.companyId = companyId;
this.currencyId = currencyId;
this.languageId = languageId
to
if (mainRoleId) { this.mainRoleId = mainRoleId;}
if (companyId) { this.companyId = companyId; }
if (currencyId) { this.currencyId = currencyId; }
if (languageId ) { this.languageId = languageId }
bad coding causes bad problems

Grails : Error initializing spring security on server restart

I have a very strange behaviour on a production server.
When I start for the first time my server, there is no problem, but when I want to stop and restart it, I get the following error :
Configuring Spring Security Core ...
... finished configuring Spring Security Core
2013-10-31 12:03:08,156 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing the application: null
java.lang.NullPointerException
at com.aftmevent.security.UserRole.create(UserRole.groovy:32)
at BootStrap$_closure1.doCall(BootStrap.groovy:16)
at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:308)
at grails.util.Environment.executeForEnvironment(Environment.java:301)
at grails.util.Environment.executeForCurrentEnvironment(Environment.java:277)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
2013-10-31 12:03:08,156 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing Grails: null
java.lang.NullPointerException
at com.aftmevent.security.UserRole.create(UserRole.groovy:32)
at BootStrap$_closure1.doCall(BootStrap.groovy:16)
at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:308)
at grails.util.Environment.executeForEnvironment(Environment.java:301)
at grails.util.Environment.executeForCurrentEnvironment(Environment.java:277)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
oct. 31, 2013 12:03:08 PM org.apache.catalina.core.StandardContext startInternal
Here is my BootStrap.groovy :
class BootStrap {
def springSecurityService
def init = { servletContext ->
def existingAdminRole = Role.findByAuthority('ROLE_ADMIN')
def existingUserRole = null
def existingAdminUser = null
if (existingAdminRole) {
existingUserRole = UserRole.findByRole(existingAdminRole)
}
if (existingUserRole) {
existingAdminUser = existingUserRole.user
}
if (!existingAdminUser) {
def adminRole = new Role(authority: 'ROLE_ADMIN')
def adminUser = new User(username: 'admin', password: 'admin', enabled: true)
if (adminRole.validate()) {
adminRole.save(flush: true, failOnError: true)
}
if (adminUser.validate()) {
adminUser.save(flush: true, failOnError: true)
}
UserRole userRole = UserRole.create(adminUser, adminRole, true)
if (userRole.validate()) {
userRole.save(flush: true, failOnError: true)
}
}
}
def destroy = {
}
}
Here is my User.groovy (adding the nullable constraint did not solve the problem) :
User.groovy :
class User {
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static constraints = {
username nullable: true, blank: false, unique: true
password nullable: true, blank: false
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
Here are my classe Role.groovy and UserRole.groovy :
Role.groovy :
class Role {
String authority
static mapping = {
cache true
}
static constraints = {
authority nullable: true, blank: false, unique: true
}
}
UserRole.groovy :
class UserRole implements Serializable {
User user
Role role
boolean equals(other) {
if (!(other instanceof UserRole)) {
return false
}
other.user?.id == user?.id &&
other.role?.id == role?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (user) builder.append(user.id)
if (role) builder.append(role.id)
builder.toHashCode()
}
static UserRole get(long userId, long roleId) {
find 'from UserRole where user.id=:userId and role.id=:roleId',
[userId: userId, roleId: roleId]
}
static UserRole create(User user, Role role, boolean flush = false) {
new UserRole(user: user, role: role).save(flush: flush, insert: true)
}
static boolean remove(User user, Role role, boolean flush = false) {
UserRole instance = UserRole.findByUserAndRole(user, role)
if (!instance) {
return false
}
instance.delete(flush: flush)
true
}
static void removeAll(User user) {
executeUpdate 'DELETE FROM UserRole WHERE user=:user', [user: user]
}
static void removeAll(Role role) {
executeUpdate 'DELETE FROM UserRole WHERE role=:role', [role: role]
}
static mapping = {
id composite: ['role', 'user']
version false
}
}
Here is my DataSource.groovy file with the database settings :
environments {
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
driverClassName = 'com.mysql.jdbc.Driver'
username = 'root'
password = 'root'
url = 'jdbc:mysql://localhost:3306/database?autoreconnect=true&useUnicode=true&characterEncoding=utf-8'
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
}
}
production {
dataSource {
dbCreate = 'create-drop'
driverClassName = 'com.mysql.jdbc.Driver'
username = 'root'
password = 'root'
url = 'jdbc:mysql://localhost:3306/database?autoreconnect=true&useUnicode=true&characterEncoding=utf-8'
}
}
}
I really don't have any idea about what occured.
I have added the nullable constrainst, trying to put the databe into 'create-drop' / 'update'.
Funny thing : When I drop the databse then create it again, the first server start is good, but crash after a restart.
I try to put println logs into my BootStrap.groovy, I can see them into development environment, but not into production server.
So I'm not sure if my BootStrap is updated creating war.
I create the war using :
grails prod war target/my-new-war-0.0.x.war
Thanks for reading,
Snite
I'm not really sure what's wrong with your code, however your giant block of code was making my head hurt so I had to post this.
Role role = Role.findByAuthority("ROLE_ADMIN") ?: new Role(authority: "ROLE_ADMIN").save(flush: true, failOnError: true)
if (UserRole.countByRole(role) == 0) {
User user = new User(username: 'admin', password: 'admin', enabled: true).save(flush: true, failOnError: true)
UserRole.create(user, role, true)
}
hmmm well its a null point exception:
ERROR context.GrailsContextLoader - Error initializing the application: null
java.lang.NullPointerException
at com.aftmevent.security.UserRole.create(UserRole.groovy:32)
at BootStrap$_closure1.doCall(BootStrap.groovy:16)
Unsure if the pasted content matches up exactly to your own line numbers, something you could try for now is by going around and adding the question mark :
def existingAdminRole = Role.findByAuthority('ROLE_ADMIN')
def existingUserRole = null
def existingAdminUser = null
if (existingAdminRole) {
existingUserRole = UserRole.findByRole(existingAdminRole)
}
if (existingUserRole) {
existingAdminUser = existingUserRole.user
}
change to:
def existingAdminRole = Role?.findByAuthority('ROLE_ADMIN')
def existingUserRole = null
def existingAdminUser = null
if (existingAdminRole) {
existingUserRole = UserRole?.findByRole(existingAdminRole)
}
if (existingUserRole) {
existingAdminUser = existingUserRole?.user
}
Also you could try findorsavewhere rather than an attempt to generate a new record:
https://github.com/vahidhedayati/ajaxdependancyselectexample/blob/master/grails-app/conf/BootStrap.groovy
def n1=MyContinent.findOrSaveWhere(continentName: 'Asia')
def n2=MyContinent.findOrSaveWhere(continentName: 'Europe')
// Create countries and provde continent map value as above defs
def c1 = MyCountry.findOrSaveWhere(mycontinent: n2, countryName:'United Kingdom',ccode:'GB',language:'')
def c2 = MyCountry.findOrSaveWhere(mycontinent: n2, countryName:'France',ccode:'FR',language:'')
def c3 = MyCountry.findOrSaveWhere(mycontinent: n1, countryName:'China',ccode:'CN',language:'')
def c4 = MyCountry.findOrSaveWhere(mycontinent: n1, countryName:'India',ccode:'IN',language:'')
you will need to figure out what is going on in line 32 of UserRole which will be the start of your issue followed by BootStrap on line 16..
Thanks for all of your answer which help me to solve my issue.
It was stupid but in my rundeck script to deploy the war on the production server, it was an out of date version of the war which was used -_-
So doint it manually with the correct war version solve my problem.
Thanks because your advices help me to read adequat documentation on grails's framework and help me thinking looking here.
Cheers,
Snite

how to get contacts created by currently logged in user in grails

I have implemented spring security service for user authentication in my grails application.
I have Subscriber.groovy(user table) and Contact.groovy domains. Once a subscriber(user) logs in, he/she can create contacts.There is hasMany relationship between Subscriber and Contact domain.
Problem: I have implemented search functionality for contacts created by currently logged user or subscriber on contact page. It works fine but it fetch all contacts in system but I want only contacts those are created by currently logged in subscriber(user).
How to search contacts those are created by currently logged in subscriber.
Method for searching contacts from contact table
def searchAJAX = {
def contacts = Contact.findAllByNameLike("%${params.query}%")
//Create XML response
render(contentType: "text/xml") {
results() {
contacts.each { contact ->
result(){
name(contact.name)
//Optional id which will be available in onItemSelect
id(contact.id)
}
}
}
}
}
ContactController.groovy
package com.vproc.member
import grails.converters.*
class ContactController {
def springSecurityService
def subscriberService
def imageUploadService
def searchableService
def autoCompleteService
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index() {
redirect(action: "list", params: params)
}
def list() {
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
List<Contact>contactsList = new ArrayList<Contact>();
loggedinSubscriber?.contacts.each { it ->
contactsList.add(it)
}
[contactInstanceList:contactsList , contactInstanceTotal: contactsList.size() ]
}
def create() {
[contactInstance: new Contact(params)]
}
def save() {
// params.birthday = Date.parse( 'MM/dd/yyyy', params.birthday )
if (params.birthday){
params.birthday = (new SimpleDateFormat("MM/dd/yyyy")).parse(params.birthday)
}
def contactInstance = new Contact(params)
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
if (loggedinSubscriber == null)
System.out.println("not able to save")
else {
if (!loggedinSubscriber.contacts){
loggedinSubscriber.contacts = new ArrayList<Contact>();
}
loggedinSubscriber.contacts.add(contactInstance)
if (!loggedinSubscriber.save(flush: true)) {
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
render(view: "create", model: [contactInstance: contactInstance])
return
}
}
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
redirect(action: "list")
}
// enable search for contacts
def contact_search = {
def query = params.q
if(query){
def srchResults = searchableService.search(query)
render(view: "list",
model: [contactInstanceList: srchResults.results,
contactInstanceTotal:srchResults.total])
}
else{
render "not record found";
}
}
// fetch name from contact table for autocomplete on contact
def searchAJAX = {
def contacts = Contact.findAllByNameLike("%${params.query}%")
//Create XML response
render(contentType: "text/xml") {
results() {
contacts.each { contact ->
result(){
name(contact.name)
//Optional id which will be available in onItemSelect
id(contact.id)
}
}
}
}
}
}
Contact.groovy
package com.vproc.member
import java.util.Date;
import com.vproc.common.Tag;
import com.vproc.enquiry.ContactType;
import grails.converters.JSON;
class Contact {
String name
String phoneNumber
String emailAddress
Gender gender
String url
String note
byte[] image
String address
Date dateCreated
Date lastUpdated
ContactType contactType
Date birthday
static belongsTo = [Subscriber]
static hasMany = [tags:Tag , shares: SharedContact]
static constraints = {
image nullable: true
phoneNumber nullable: true
url nullable :true
address nullable :true
gender nullable :true
note nullable :true
contactType nullable :true
birthday nullable :true
}
static mapping = {
note(type: 'text')
}
//static searchable = [only: ['name', 'emailAddress']]
static searchable = true
static scaffold = true
//static searchable = true
}
Subscriber.groovy
package com.vproc.member
import java.util.Date;
import com.vproc.common.StatusEnum;
import com.vproc.enquiry.Discussion;
import com.vproc.enquiry.Enquiry;
import com.vproc.enquiry.Membership;
import com.vproc.enquiry.Notification;
import com.vproc.enquiry.SharedEnquiry;
import com.vproc.enquiry.Team;
import com.vproc.order.Seat;
class Subscriber extends PartyRole{
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
StatusEnum status
Date dateCreated
Date lastUpdated
List<Contact> contacts ;
static belongsTo = [ customer: Customer]
static hasMany = [seats: Seat, ownedEnquiries: Enquiry,enquiresSharedWith: SharedEnquiry, enquiriesSharedBy: SharedEnquiry ,
managedTeams: Team , memberships: Membership, contacts: Contact , sharedByContacts: SharedContact, sharedWithContacts: SharedContact,
vContacts: VContact, partOf: VContact, sharedbyVContacts: SharedVcontact, sharedWithVcontacts: SharedVcontact,
notifications: Notification, discussions: Discussion]
static mappedBy = [ managedTeams : "manager" , enquiresSharedWith: "sharedWith" , enquiriesSharedBy: "sharedBy" ,
sharedByContacts : "sharedBy" , sharedWithContacts : "sharedWith" ,
vContacts: "forSubscriber" , partOf :"ofContact",
sharedbyVContacts: "sharedby" , sharedWithVcontacts :"sharedWith"
]
static constraints = {
username validator : { val , obj ->
if (obj.status != StatusEnum.Pending)
val!= null
}
username unique: true
password validator : { val , obj ->
if (obj.status != StatusEnum.Pending)
val != null
}
contacts nullable: true
notifications nullable : true
username nullable: true
password nullable: true
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
SubscriberRole.findAllBySubscriber(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
save action for Contact controller
def save() {
// params.birthday = Date.parse( 'MM/dd/yyyy', params.birthday )
if (params.birthday){
params.birthday = (new SimpleDateFormat("MM/dd/yyyy")).parse(params.birthday)
}
def contactInstance = new Contact(params)
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
if (loggedinSubscriber == null)
System.out.println("not able to save")
else {
if (!loggedinSubscriber.contacts){
loggedinSubscriber.contacts = new ArrayList<Contact>();
}
loggedinSubscriber.contacts.add(contactInstance)
if (!loggedinSubscriber.save(flush: true)) {
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
render(view: "create", model: [contactInstance: contactInstance])
return
}
}
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
redirect(action: "list")
}
Note: while saving contacts,I have logged in subscriber in save action of Contact controller but I do not know how to use it below method which is searchAjax for searching contacts.
Assuming Subscriber has an association to Contact as,
class Subscriber {
static hasMany = [contacts: Contact]
}
then, to get all contacts for a subscriber user,
subscriberInstance.contacts
and to query among contacts of the same subscriber use,
subscriberInstance.findByContact('your_query_string')
For reference look up querying associations on the documentation http://grails.org/doc/latest/guide/GORM.html#querying

grails spring security login is not working

I am using grails 2.1.0. I have installed spring-security-core plugin.
When I create user it is creating it. But when I try to login then it shows:
"Sorry, we were not able to find a user with that username and password."
And there is also another fact that is when I use the same password for different user it does not save password with similar encoded value like for user 1 I have used password 123 which is saved in database like this
d535ce213a0e8e4f9e724af47c46eea409ef401c03617b749da618a82890d743
and for user 2 I also used password 123 and this time it is saved like this
0849ea79a2c1bca057ded06c3053fb5bc5d7ba52b50982e73e44894d4f3e0aa6
I don't understand. Can anyone please help me on this ?
my config.groovy >>>
// locations to search for config files that get merged into the main config;
// config files can be ConfigSlurper scripts, Java properties files, or classes
// in the classpath in ConfigSlurper format
// grails.config.locations = [ "classpath:${appName}-config.properties",
// "classpath:${appName}-config.groovy",
// "file:${userHome}/.grails/${appName}-config.properties",
// "file:${userHome}/.grails/${appName}-config.groovy"]
// if (System.properties["${appName}.config.location"]) {
// grails.config.locations << "file:" + System.properties["${appName}.config.location"]
// }
grails.project.groupId = appName // change this to alter the default package name and Maven publishing destination
grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
grails.mime.use.accept.header = false
grails.mime.types = [
all: '*/*',
atom: 'application/atom+xml',
css: 'text/css',
csv: 'text/csv',
form: 'application/x-www-form-urlencoded',
html: ['text/html','application/xhtml+xml'],
js: 'text/javascript',
json: ['application/json', 'text/json'],
multipartForm: 'multipart/form-data',
rss: 'application/rss+xml',
text: 'text/plain',
xml: ['text/xml', 'application/xml']
]
// URL Mapping Cache Max Size, defaults to 5000
//grails.urlmapping.cache.maxsize = 1000
// What URL patterns should be processed by the resources plugin
grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*']
// The default codec used to encode data with ${}
grails.views.default.codec = "none" // none, html, base64
grails.views.gsp.encoding = "UTF-8"
grails.converters.encoding = "UTF-8"
// enable Sitemesh preprocessing of GSP pages
grails.views.gsp.sitemesh.preprocess = true
// scaffolding templates configuration
grails.scaffolding.templates.domainSuffix = 'Instance'
// Set to false to use the new Grails 1.2 JSONBuilder in the render method
grails.json.legacy.builder = false
// enabled native2ascii conversion of i18n properties files
grails.enable.native2ascii = true
// packages to include in Spring bean scanning
grails.spring.bean.packages = []
// whether to disable processing of multi part requests
grails.web.disable.multipart=false
// request parameters to mask when logging exceptions
grails.exceptionresolver.params.exclude = ['password']
// configure auto-caching of queries by default (if false you can cache individual queries with 'cache: true')
grails.hibernate.cache.queries = false
environments {
development {
grails.logging.jul.usebridge = true
}
production {
grails.logging.jul.usebridge = false
// TODO: grails.serverURL = "http://www.changeme.com"
}
}
// log4j configuration
log4j = {
// Example of changing the log pattern for the default console appender:
//
//appenders {
// console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
//}
error 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages', // GSP
'org.codehaus.groovy.grails.web.sitemesh', // layouts
'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
'org.codehaus.groovy.grails.web.mapping', // URL mapping
'org.codehaus.groovy.grails.commons', // core / classloading
'org.codehaus.groovy.grails.plugins', // plugins
'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
'org.springframework',
'org.hibernate',
'net.sf.ehcache.hibernate'
}
// Added by the Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'common.auth.User'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'common.auth.UserAuthority'
grails.plugins.springsecurity.authority.className = 'common.auth.Authority'
my login controller >>>
import grails.converters.JSON
import javax.servlet.http.HttpServletResponse
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import org.springframework.security.authentication.AccountExpiredException
import org.springframework.security.authentication.CredentialsExpiredException
import org.springframework.security.authentication.DisabledException
import org.springframework.security.authentication.LockedException
import org.springframework.security.core.context.SecurityContextHolder as SCH
import org.springframework.security.web.WebAttributes
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
class LoginController {
/**
* Dependency injection for the authenticationTrustResolver.
*/
def authenticationTrustResolver
/**
* Dependency injection for the springSecurityService.
*/
def springSecurityService
/**
* Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise.
*/
def index = {
if (springSecurityService.isLoggedIn()) {
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
} else {
redirect action: 'auth', params: params
}
}
/**
* Show the login page.
*/
def auth = {
def config = SpringSecurityUtils.securityConfig
if (springSecurityService.isLoggedIn()) {
redirect uri: config.successHandler.defaultTargetUrl
return
}
String view = 'auth'
String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
render view: view, model: [postUrl: postUrl,
rememberMeParameter: config.rememberMe.parameter]
}
/**
* The redirect action for Ajax requests.
*/
def authAjax = {
response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl
response.sendError HttpServletResponse.SC_UNAUTHORIZED
}
/**
* Show denied page.
*/
def denied = {
if (springSecurityService.isLoggedIn() &&
authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
// have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
redirect action: 'full', params: params
}
}
/**
* Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
*/
def full = {
def config = SpringSecurityUtils.securityConfig
render view: 'auth', params: params,
model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication),
postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"]
}
/**
* Callback after a failed login. Redirects to the auth page with a warning message.
*/
def authfail = {
def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
String msg = ''
def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
if (exception) {
if (exception instanceof AccountExpiredException) {
msg = g.message(code: "springSecurity.errors.login.expired")
} else if (exception instanceof CredentialsExpiredException) {
msg = g.message(code: "springSecurity.errors.login.passwordExpired")
} else if (exception instanceof DisabledException) {
msg = g.message(code: "springSecurity.errors.login.disabled")
} else if (exception instanceof LockedException) {
msg = g.message(code: "springSecurity.errors.login.locked")
} else {
msg = g.message(code: "springSecurity.errors.login.fail")
}
}
if (springSecurityService.isAjax(request)) {
render([error: msg] as JSON)
} else {
flash.message = msg
redirect action: 'auth', params: params
}
}
/**
* The Ajax success redirect url.
*/
def ajaxSuccess = {
render([success: true, username: springSecurityService.authentication.name] as JSON)
}
/**
* The Ajax denied redirect url.
*/
def ajaxDenied = {
render([error: 'access denied'] as JSON)
}
}
my authority.groovy >>>
package common.auth
class Authority {
String authority
static mapping = {
cache true
}
static constraints = {
authority blank: false, unique: true
}
}
my user domain.groovy where my user will be saved >>>
package common.auth
class User {
transient springSecurityService
String realname
String username
String password
String designation
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set<Authority> getAuthorities() {
UserAuthority.findAllByUser(this).collect { it.authority } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
my userauthority.groovy >>>
package common.auth
import org.apache.commons.lang.builder.HashCodeBuilder
class UserAuthority implements Serializable {
User user
Authority authority
boolean equals(other) {
if (!(other instanceof UserAuthority)) {
return false
}
other.user?.id == user?.id &&
other.authority?.id == authority?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (user) builder.append(user.id)
if (authority) builder.append(authority.id)
builder.toHashCode()
}
static UserAuthority get(long userId, long authorityId) {
find 'from UserAuthority where user.id=:userId and authority.id=:authorityId',
[userId: userId, authorityId: authorityId]
}
static UserAuthority create(User user, Authority authority, boolean flush = false) {
new UserAuthority(user: user, authority: authority).save(flush: flush, insert: true)
}
static boolean remove(User user, Authority authority, boolean flush = false) {
UserAuthority instance = UserAuthority.findByUserAndAuthority(user, authority)
if (!instance) {
return false
}
instance.delete(flush: flush)
true
}
static void removeAll(User user) {
executeUpdate 'DELETE FROM UserAuthority WHERE user=:user', [user: user]
}
static void removeAll(Authority authority) {
executeUpdate 'DELETE FROM UserAuthority WHERE authority=:authority', [authority: authority]
}
static mapping = {
id composite: ['authority', 'user']
version false
}
}
And my createUser action to create user in AdministratorActionController >>>
package administrator
import common.auth.User
class AdmistratorActionController {
def springSecurityService
def index() {
redirect(controller: 'admistratorAction', action: 'createUser')
}
def createUser = {
User user = new User(params)
def password = user.password
def salt = user.username //depends on what you're using as a salt
user.password = springSecurityService.encodePassword(password, salt)
user.save()
flash.message = "User Create Successfully !!!"
}
}
I think you are encoding your password twice, you already have encode() on beforeInsert in the domain, I think you need not to encode it again.
Spring Security use hash of user password + a salt. Salt is used to defeat pre-computed rainbow table attacks that could otherwise be used to greatly improve the efficiency of cracking the hashed password database. See http://en.wikipedia.org/wiki/Salt_(cryptography)
For example, if we're using username as a hash, real value in database will be:
md5(user.password + '|' + user.username)
So for two different userw with same password:
user: username: 'user1', password: 123
user: username: 'user2', password: 123
you'll get two different values in database:
md5('user1|123') == 975204d0650cc642730866d56f66b6fb
md5('user2|123') == aa12022115555842a7f80564940ae49d
So, if hacker have access to you database he cannot guess the password.
Spring Security uses same hashing function and salt for saving and loading user. And if it unable to find user it probably means that you've used different salt for initial save and for later load from the database. Make sure that you have same salt source, and it's not changing (like id field, that have null value when you just creating a new user)

Resources