I have a very simple User
model, and my entire main.go
is the following
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"golang.org/x/crypto/bcrypt"
)
// User : the user data model
type User struct {
gorm.Model
Username string `gorm:"type:varchar(40);unique" json:"username,omitempty"`
Password string `gorm:"size:255" json:"password,omitempty"`
}
// BeforeSave : hook before a user is saved
func (u *User) BeforeSave(scope *gorm.Scope) (err error) {
fmt.Println("before save")
fmt.Println(u.Password)
if u.Password != "" {
hash, err := MakePassword(u.Password)
if err != nil {
return nil
}
u.Password = hash
}
fmt.Println(u.Password)
return
}
// MakePassword : Encrypt user password
func MakePassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes), err
}
func main() {
var connectionString = fmt.Sprintf(
"%s:%s@/%s?charset=utf8&parseTime=True&loc=Local",
"root", "password", "project",
)
db, _ := gorm.Open("mysql", connectionString)
db.AutoMigrate(&User{})
db.Save(&User{
Username: "name1",
Password: "123",
})
db.Model(&User{
Model: gorm.Model{ID: 1},
}).Update(&User{
Username: "name2",
Password: "12345",
})
}
For the first time of my creation, the password is created and save as a hash string (I commented out the second updating part and tested it), but when I updating it, it is saved as plain text.
From the console, I can see the Println
message, BeforeUpdate
is trigged, and I see the plain password and MD5 of it, but in database, it is saved as plain text.
before save
123
$2a$10$Vknv/uu7tAPRQSddPVlQ7OodIHZJmRPKktjb98U8U5.GT/OLQeQE2
before save
12345
$2a$10$K0ZkLH7slfiFmkOe5DTKr.DGNvR6HtpjxCS/1svf2ZEvfTXVkMkvu
Any ideas on how I can fix it ?
According to the docs in order to change the values being updated you must set them through the gorm Scope param. The User struct in this case it's not meant to be used for modifications. You should use SetColumn instead.
// BeforeUpdate : hook before a user is updated
func (u *User) BeforeUpdate(scope *gorm.Scope) (err error) {
fmt.Println("before update")
fmt.Println(u.Password)
if u.Password != "" {
hash, err := MakePassword(u.Password)
if err != nil {
return err
}
scope.SetColumn("Password", hash)
}
fmt.Println(u.Password)
return
}