我使用Grails 2.0.0.RC2,我有一个像这样的User类:
class User {
String username
String password
// Idea from http://grailsrecipes.wordpress.com/2009/04/19/grails-user-registration-and-login/ .
String formPassword
String formPasswordConfirm
// Constraints and validation ommited
static transients = ['formPassword', 'formPasswordConfirm']
def beforeUpdate() {
println("Inside beforeUpdate")
if (formPassword != null)
encodePassword()
}
protected void encodePassword() {
password = formPassword // Just for this case
}
}
当用户要求重置密码时,我会向他发送一封电子邮件,其中包含重置密码页面的链接。重置密码表单很简单 - 它只包含两个字段:formPassword
和formPasswordConfirm
。我在控制器中执行了一个简单的操作:user.formPassword = params["formPassword"]
和user.formPasswordConfirm = params["formPasswordConfirm"]
。然后我做(user.save()
) - 问题就开始了。
我的问题是没有调用beforeUpdate()
。我认为这是一个验证问题(这里是omiited),但事实并非如此。事实证明user.save()
没有将用户持久化到数据库!为什么?我希望它被持久化,密码应该改变。但是user.isDirty()
之前user.save()
是假的。那是因为没有任何持久性属性被改变。确实如此。由于未调用user.save()
,因此未调用beforeUpdate()
。
这是理想的行为吗?也许这是一个Grails错误,在更新之前应该始终调用beforeUpdate()
,然后应该检查isDirty()
?你觉得怎么样?
答案 0 :(得分:3)
我不知道在更新瞬态字段时是否应该调用beforeUpdate
,但是可以选择
我会在2上投入大量资金,在1上投注很少。
所以把它放在一边,我认为你已经使你的域类变得更复杂了。具体来说,您应该能够通过2个密码字段而不是3来实现目标。
class User {
static transients = ['passwordConfirm']
def springSecurityService
String password
String passwordConfirm
static constraints = {
password blank: false, validator: {password, self ->
// We only need to check the password confirmation when it is not empty, i.e.
// when a user registers or resets their password
if (self.passwordConfirm) {
password == self.passwordConfirm
}
}
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
private void encodePassword() {
password = springSecurityService.encodePassword(password)
passwordConfirm = springSecurityService.encodePassword(passwordConfirm)
}
}
您的重置密码控制器操作应如下所示:
def resetPassword = {
User user = User.findByUsername(params.username)
user.password = params.formPassword
user.passwordConfirm = params.formPasswordConfirm
if (user.save()) {
// It worked, send them to the login page or whatever...
} else {
// Validation failed, send them back to the reset password page
}
}
答案 1 :(得分:1)
这是理想的行为。
在我看来,语义非常清晰,你没有改变任何持久字段,因此没有什么可以保存的。 .save()无法猜测在这种情况下,某些瞬态属性应该让你运行save()(然后是beforeUpdate())。
只需添加一个更新密码的方法就可以了。