grails プロジェクトで spring security core プラグインを使用しています。Person ドメインは次のようになります。
class User {
transient springSecurityService
//Mandatory Fields
String employeeId
String firstName
String lastName
String password
String emailId
//Other Fields
String department
String extn
String mobileNumber
String address
String city
String zipCode
String country
User manager
static hasMany = [previousPasswords: String]
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static transients = ['springSecurityService']
static constraints = {
employeeId blank: false, unique: true
firstName blank: false
lastName blank: false
password blank: false, password: true, validator: {val, obj ->
if(obj.previousPasswords) {
println "-----------------------1-------------------------"
println "obj.previousPasswords: " + obj.previousPasswords
println "val: " + val
if (obj.isDirty('password')) {
println "-----------------------2-------------------------"
if(obj.previousPasswords.contains(val)) {
obj.errors.rejectValue(
'password',
'user.password.duplicated',
'Repeat passwords are not allowed')
return false
}
println "-----------------------3-------------------------"
obj.addToPreviousPasswords(val)
return true
}
} else {
println "-----------------------4-------------------------"
obj.addToPreviousPasswords(val)
return true
}
}
emailId blank: false, email: true
department nullable: true
extn nullable: true
mobileNumber nullable: true
address nullable: true
city nullable: true
zipCode nullable: true
country nullable: true
manager nullable: true
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
def beforeInsert() {
println "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
println "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
「パスワード」フィールドのカスタムバリデーターを作成したパスワードが繰り返されないようにする必要があります
私の統合テストは次のようになります
void "Test if previous passwords can be re-used"() {
given:
def user = new User(employeeId: "empId1", firstName: "f_name", lastName: "l_name", password: "password", emailId: "test@hptest.com", mobileNumber: "(111) 111-1111", address: "350 Fifth Avenue, 34th floor", city: "New York", zipCode: "10007")
println "&&&&&&&&&&&&&&&&&&& 1 &&&&&&&&&&&&&&&&&&&&&&"
user.springSecurityService = springSecurityService
println "&&&&&&&&&&&&&&&&&&& 2 &&&&&&&&&&&&&&&&&&&&&&"
user.save(flush: true, failOnError: true)
when: 'password is repeated'
user.password = "password"
println "&&&&&&&&&&&&&&&&&&& 3 &&&&&&&&&&&&&&&&&&&&&&"
user.save(flush: true)
then: 'validation fails'
!user.validate()
user.errors.getFieldError("password").codes.contains("validator.invalid")
when: 'password is not repeated'
user.password = "password@123"
then: 'validation succeeds'
println "&&&&&&&&&&&&&&&&&&& 4 &&&&&&&&&&&&&&&&&&&&&&"
user.validate()
println "&&&&&&&&&&&&&&&&&&& 5 &&&&&&&&&&&&&&&&&&&&&&"
user.save(flush: true)
}
そして、私が得ている出力はこのようなものです
&&&&&&&&&&&&&&&&&&& 1 &&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& 2 &&&&&&&&&&&&&&&&&&&&&&
-----------------------4-------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-----------------------1-------------------------
obj.previousPasswords: [password]
val: $2a$10$mxFM9S7mEoOdyRo6xJL9/uzVafUgc0.8r1rd4nzBYM45s2cE8TTDi
&&&&&&&&&&&&&&&&&&& 3 &&&&&&&&&&&&&&&&&&&&&&
-----------------------1-------------------------
obj.previousPasswords: [password]
val: password
-----------------------2-------------------------
-----------------------1-------------------------
obj.previousPasswords: [password]
val: password
コードと出力を注意深く調べると、保存操作ごとにバリデータ関数が 2 回呼び出されていることがわかります。
この理由を誰か教えてください。これは、バリデータ内で使用している addTo メソッドが原因でしょうか?