I have this:
class Usuario {
String username
String password
String passwordDos
String nombre
String apellidoPaterno
String apellidoMaterno
Date fechaDeNacimiento
String sexo
String correo
static constraints = {
username blank: false, unique: true, validator: { val, obj ->
obj.password != val
return ['usuario.userPassError']
}
password blank: false, validator: { val, obj ->
obj.passwordDos == val
return ['usuario.passDiferentes']
}
passwordDos blank: false
nombre blank: false, maxSize: 64
apellidoPaterno blank: false, maxSize: 64
apellidoMaterno blank: true, maxSize: 64
sexo inList: ["Femenino", "Masculino"]
correo blank: false, maxSize: 128, email:true
}
}
I want to return in the error message, but I'm not doing wrong, I could explain alguein please?
I'd expect there to be some sort of conditional return in the validator closures. As it stands, it looks like they'll always fail, returning the error code.
Try writing your custom validators like:
// username validator
validator: { val, obj ->
obj.password == val ? 'userPassError' : true
}
// password validator
validator: { val, obj ->
obj.passwordDos != val ? 'passDiferentes' : true
}
Note the different message codes that are being returned, too.
Then, make sure you have the following in your appropriate grails-app/i18n/messages* file(s):
usuario.username.userPassError = Username and password cannot be the same
usuario.password.passDiferentes = Password does not match password confirmation
Related
Hello today I've started to learn Grails 3 with Spring Security Core Plugin but I'm having hard time with password Validation. When user is registering I want him to type password and confirmPassword. Everything would be ok if not hashing the password. I want my password to be encoded in database but with encoding I'm not able to compare those 2 passwords.
Here is my class:
#EqualsAndHashCode(includes='username')
#ToString(includes='username', includeNames=true, includePackage=false)
class User implements Serializable {
private static final long serialVersionUID = 1
transient springSecurityService
String username
String password
String confirmPass
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
User(String username, String password) {
this()
this.username = username
this.password = password
this.confirmPass = password
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this)*.role
}
// because of that I can't compare password and confirmPass
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}
static transients = ['springSecurityService']
static constraints = {
username blank: false, unique: true
password blank: false, size: 5..60, password: true, display: false, validator: { val, obj ->
if (!obj.id && !obj.password) {
return 'validation.user.password' // my message
}
}
confirmPass blank: // now I'm stuck here, I've tried isPasswordValid() but won't work cuz of 'salt' What shout go here?
}
static mapping = {
password column: '`password`'
}
}
What should I do to make it working(valid both password are same and then encoded password store in database).
This is my domain class
class TimesheetSubmission {
Date submissionDate=new Date()
String foreman
String shift
String jobId
Date date
byte[] xmlSubmission
String xmlResponse
static constraints = {
submissionDate nullable: false
foreman nullable: false
shift nullable: false
jobId nullable: false
date nullable: false
xmlSubmission nullable: true
xmlResponse nullable: false
}
static mapping = {
xmlSubmission (type: "blob")
}
}
And following is my code to persist data in database.
TimesheetSubmission timesheetSubmission=new TimesheetSubmission()
timesheetSubmission.foreman=Party.findById(foremanId)
timesheetSubmission.shift=shift
timesheetSubmission.jobId=jobId
timesheetSubmission.date=Date.parse("yyyy-MM-dd", date)
timesheetSubmission.xmlSubmission=sTimesheet.getBytes();
timesheetSubmission.xmlResponse="response"
timesheetSubmission.save(flush: true,failOnError: true)
I am getting following error when applying save on domain .
[B cannot be cast to java.sql.Blob
static mapping = {
xmlSubmission sqlType: 'blob'
}
I need your help in this scenario.
I have the following domain class:
class Payment {
BigDecimal cash
BigDecimal checkValue
static constraints = {
cash nullable: true
checkValue nullable: true
}
}
The cash and checkValue properties are nullable, but at least one of them has to have a value.
I hope I was able to explain my problem.
Thanks for your time!
Custom validator seems to be a good option in this case. Try with:
class Payment {
BigDecimal cash
BigDecimal checkValue
static constraints = {
cash nullable: true, validator: { val, obj ->
val != null || obj.checkValue != null
}
checkValue nullable: true, validator: { val, obj ->
val != null || obj.cash != null
}
}
}
With groovy truth you can simplify the validator closures to something like below:
static constraints = {
cash nullable: true, validator: { val, obj -> val || obj.checkValue }
checkValue nullable: true, validator: { val, obj -> val || obj.cash }
}
For more information take a look at Validation section of grails documentation.
This is my user class that has Spring Security on it
package rms
import java.util.Date;
import java.util.Set;
import enums.EmployeeStatus;
class User {
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
String firstName
String lastName
String middleName
String contactNumber
String position
String emailAddress
String employeeID
Date dateOfBirth
EmployeeStatus employeeStatus
int age
byte [] picture
static hasMany = [employeeReport: EmployeeReport]
static constraints = {
picture maxSize:20* 1024 * 1024
dateOfBirth nullable: true
employeeStatus blank: false
position blank: false
contactNumber blank: false
emailAddress blank: false, matches: "([a-z0-9_.-]+)#([da-z.-]+).([a-z.]{2,6})", email: true
age min: 18
username blank: false, unique: true
password blank: false, password: true
}
static mapping = { password column: '`password`' }
Set<SecRole> getAuthorities() {
SecUserSecRole.findAllBySecUser(this).collect { it.secRole } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
String toString(){
return "SecUser $username"
}
}
I tried this tag <sec:loggedInUserInfo field="username"/> and it works fine but this doesn't work <sec:loggedInUserInfo field="firstName"/>. It gives a
No such property: firstName for class: org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser
Is there any other way to display the other properties of the current logged in user?
The loggedInUserInfo can only access data from the "principal", which is typically an instance of GrailsUser. The data includes username, id, the assigned role names, and a few booleans about whether the user is enabled, the account is locked, etc. It's easy to subclass GrailsUser and create your own UserDetailsService and capture other data from the user domain class during authentication, and store that in the GrailsUser subclass to make it available to this tag; see http://grails-plugins.github.io/grails-spring-security-core/docs/manual.1273/guide/11%20Custom%20UserDetailsService.html for more info.
This works well if the data is read-only since it will be cached until the user logs out or the session expires. If the data that you want to display can change, retrieve the user instance and add it to the model map you return from the controller action:
class MyController {
def springSecurityService
def theAction() {
...
def user = springSecurityService.currentUser
[user: user, foo: 5, bar: "whatever", ...]
}
}
and then you can display whatever you want in the GSP, e.g. ${user.firstName}
I have installed the grails Spring-Security plugin:
plugins {
compile ':spring-security-core:2.0-RC2'
}
Then I used the grails s2-quickstart com.jane Person Role command to create the needed domain classes.
As I have my own User class I refactored the code to use my User class:
package com.jane
class User {
transient springSecurityService
String email
String name
String password
Boolean isAgreeTerms = false
Date agreeTermsDt
Boolean isActive = false
Boolean isBlocked = false
Date dateCreated
Integer createdBy = 0
Date lastUpdated
Integer modifiedBy = 0
static transients = [ 'springSecurityService' ]
static hasMany = [ userProductTier: UserProductTier ]
static mapping = {
id column: "userID"
dateCreated column: 'createdDt'
lastUpdated column: 'modifiedDT'
}
static constraints = {
email blank: false, email: true, unique: true, size: 5..100
name blank: false, size: 3..50
password blank: false
}
void beforeInsert() {
if ( isAgreeTerms ) {
agreeTermsDt = new Date()
}
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
I then modified the config.groovy file to:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.jane.User'
grails.plugin.springsecurity.userLookup.usernamePropertyName = 'email'
grails.plugin.springsecurity.userLookup.enabledPropertyName = 'isActive'
grails.plugin.springsecurity.userLookup.accountExpiredPropertyName = 'isBlocked'
grails.plugin.springsecurity.userLookup.accountLockedPropertyName = 'isBlocked'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.jane.UserRole'
grails.plugin.springsecurity.authority.className = 'com.jane.Role'
I can create users fine, verify they are in the database, have verified that encodePassword is called once. But every time I try to login I get the following error:
Sorry, we were not able to find a user with that username and
password.
And here is the service method to create users:
User createTeamLeader( String name, String email, String password, Boolean isAgreeTerms, Integer productTierId ) {
User user = new User( name: name, email: email, password: password, isAgreeTerms: isAgreeTerms, isActive: true)
UserProductTier userProductTier = new UserProductTier( productTierId: productTierId )
user.addToUserProductTier( userProductTier )
user.save()
UserRole.create( user, Role.findByAuthority('ROLE_USER'), true )
UserRole.create( user, Role.findByAuthority('ROLE_LEAD'), true )
user
}
Often adding debug logging helps, since Spring Security logs a lot at the debug level:
log4j = {
...
debug 'org.springframework.security'
}
In this case it didn't show the problem, so I added an event listener to see if there was information in the failure event:
grails.plugin.springsecurity.useSecurityEventListener = true
grails.plugin.springsecurity.onAbstractAuthenticationFailureEvent = { e, appCtx ->
println "\nERROR auth failed for user $e.authentication.name: $e.exception.message\n"
}
That displayed this:
ERROR auth failed for user ernie#ss.com: No such property: authorities for class: com.jane.User
When you made changes in the class, you removed the getAuthorities method that was in the original version, and is used by the UserDetailsService to determine granted roles during authentication. Adding it back got things working:
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}