fix: improve login error handling to distinguish database errors from auth failures

ValidateAndFill now checks the DB query result and returns sentinel errors
(ErrDatabase, ErrInvalidCredentials, ErrUserEmptyCredentials) instead of
hardcoded Chinese strings. The controller maps each sentinel to the
appropriate i18n message, so users see "please contact admin" on DB errors
instead of a misleading "wrong password" message. Non-DB errors still
return a unified vague response to avoid leaking user existence.
This commit is contained in:
CaIon
2026-04-12 17:11:20 +08:00
parent ed7f839911
commit 2819e3a1d1
5 changed files with 28 additions and 11 deletions
+16 -4
View File
@@ -18,6 +18,12 @@ import (
const UserNameMaxLength = 20
var (
ErrDatabase = errors.New("database error")
ErrInvalidCredentials = errors.New("invalid credentials")
ErrUserEmptyCredentials = errors.New("empty credentials")
)
// User if you add sensitive fields, don't forget to clean them in setupLogin function.
// Otherwise, the sensitive information will be saved on local storage in plain text!
type User struct {
@@ -597,13 +603,19 @@ func (user *User) ValidateAndFill() (err error) {
password := user.Password
username := strings.TrimSpace(user.Username)
if username == "" || password == "" {
return errors.New("用户名或密码为空")
return ErrUserEmptyCredentials
}
// find by username or email
err = DB.Where("username = ? OR email = ?", username, username).First(user).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrInvalidCredentials
}
return fmt.Errorf("%w: %v", ErrDatabase, err)
}
// find buy username or email
DB.Where("username = ? OR email = ?", username, username).First(user)
okay := common.ValidatePasswordAndHash(password, user.Password)
if !okay || user.Status != common.UserStatusEnabled {
return errors.New("用户名或密码错误,或用户已被封禁")
return ErrInvalidCredentials
}
return nil
}