|
|
package user
|
|
|
|
|
|
import (
|
|
|
"errors"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
var (
|
|
|
ErrInvalidPassword = errors.New("密码不正确")
|
|
|
ErrPasswordTooShort = errors.New("密码长度不能小于6位")
|
|
|
ErrInvalidPhone = errors.New("手机号格式不正确")
|
|
|
ErrInvalidVerifyCode = errors.New("验证码不正确")
|
|
|
ErrVerifyCodeExpired = errors.New("验证码已过期")
|
|
|
ErrPhoneNotMatch = errors.New("手机号与用户不匹配")
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
VerifyCodeKeyPrefix = "sms:verify:code:" // Redis中验证码的key前缀
|
|
|
VerifyCodeExpiration = 5 * time.Minute // 验证码有效期5分钟
|
|
|
MinPasswordLength = 6 // 密码最小长度
|
|
|
SaltLength = 16 // 盐值长度
|
|
|
)
|
|
|
|
|
|
// User 用户聚合根
|
|
|
type User struct {
|
|
|
Id uint64 `xorm:"pk autoincr 'id'" `
|
|
|
Username string `xorm:"varchar(50) notnull unique 'username'"`
|
|
|
Phone string `xorm:"varchar(60) unique 'phone'" `
|
|
|
// 密码相关
|
|
|
Password string `xorm:"varchar(60) notnull 'password'" ` // 使用 bcrypt 加密存储,长度60
|
|
|
Salt string `xorm:"varchar(32) notnull 'salt'" ` // 密码加密盐值
|
|
|
// 状态相关
|
|
|
Status int8 `xorm:"tinyint(1) default 1 'status'" `
|
|
|
// 登录相关
|
|
|
LastLoginTime *time.Time `xorm:"datetime 'last_login_time'" `
|
|
|
LastLoginIp string `xorm:"varchar(50) 'last_login_ip'"`
|
|
|
GiftCount int8 //赠送次数
|
|
|
// 时间相关
|
|
|
CreatedAt time.Time `xorm:"datetime created 'created_at'" `
|
|
|
UpdatedAt time.Time `xorm:"datetime updated 'updated_at'"`
|
|
|
DeletedAt time.Time `xorm:"datetime deleted 'deleted_at'" `
|
|
|
}
|
|
|
|
|
|
type userConfiguration func(u *User)
|
|
|
type userConfigurations []userConfiguration
|
|
|
|
|
|
// WithUsername 设置用户名
|
|
|
func WithUsername(username string) userConfiguration {
|
|
|
return func(u *User) {
|
|
|
u.Username = username
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// WithPhone 设置手机号
|
|
|
func WithPhone(phone string) userConfiguration {
|
|
|
return func(u *User) {
|
|
|
u.Phone = phone
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// NewUser 创建新用户(聚合根的工厂方法)
|
|
|
func NewUser(username, phone string, configs ...userConfiguration) *User {
|
|
|
user := &User{
|
|
|
Username: username,
|
|
|
Phone: phone,
|
|
|
Status: 1,
|
|
|
}
|
|
|
|
|
|
userConfigurations(configs).apply(user)
|
|
|
return user
|
|
|
}
|
|
|
|
|
|
func (cfg userConfigurations) apply(user *User) {
|
|
|
for _, c := range cfg {
|
|
|
c(user)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// GetUsername 实现UserDetails接口
|
|
|
func (u *User) GetUsername() string {
|
|
|
return u.Username
|
|
|
}
|
|
|
|
|
|
// GetPassword 获取加密后的密码(实现UserDetails接口)
|
|
|
func (u *User) GetPassword() string {
|
|
|
return u.Password
|
|
|
}
|
|
|
|
|
|
// IsEnabled 判断用户是否启用
|
|
|
func (u *User) IsEnabled() bool {
|
|
|
return u.Status == 1
|
|
|
}
|
|
|
|
|
|
// GetPhone 获取手机号
|
|
|
func (u *User) GetPhone() string {
|
|
|
return u.Phone
|
|
|
}
|