89 lines
2.3 KiB
Go
89 lines
2.3 KiB
Go
|
|
package entities
|
||
|
|
|
||
|
|
import (
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"gorm.io/gorm"
|
||
|
|
)
|
||
|
|
|
||
|
|
// SMSCode 短信验证码记录
|
||
|
|
type SMSCode struct {
|
||
|
|
ID string `gorm:"primaryKey;type:varchar(36)" json:"id"`
|
||
|
|
Phone string `gorm:"type:varchar(20);not null;index" json:"phone"`
|
||
|
|
Code string `gorm:"type:varchar(10);not null" json:"-"` // 不返回给前端
|
||
|
|
Scene SMSScene `gorm:"type:varchar(20);not null" json:"scene"`
|
||
|
|
Used bool `gorm:"default:false" json:"used"`
|
||
|
|
ExpiresAt time.Time `gorm:"not null" json:"expires_at"`
|
||
|
|
UsedAt *time.Time `json:"used_at,omitempty"`
|
||
|
|
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
||
|
|
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
||
|
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||
|
|
|
||
|
|
// 额外信息
|
||
|
|
IP string `gorm:"type:varchar(45)" json:"ip"`
|
||
|
|
UserAgent string `gorm:"type:varchar(500)" json:"user_agent"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// SMSScene 短信验证码使用场景
|
||
|
|
type SMSScene string
|
||
|
|
|
||
|
|
const (
|
||
|
|
SMSSceneRegister SMSScene = "register" // 注册
|
||
|
|
SMSSceneLogin SMSScene = "login" // 登录
|
||
|
|
SMSSceneChangePassword SMSScene = "change_password" // 修改密码
|
||
|
|
SMSSceneResetPassword SMSScene = "reset_password" // 重置密码
|
||
|
|
SMSSceneBind SMSScene = "bind" // 绑定手机号
|
||
|
|
SMSSceneUnbind SMSScene = "unbind" // 解绑手机号
|
||
|
|
)
|
||
|
|
|
||
|
|
// 实现 Entity 接口
|
||
|
|
func (s *SMSCode) GetID() string {
|
||
|
|
return s.ID
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *SMSCode) GetCreatedAt() time.Time {
|
||
|
|
return s.CreatedAt
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *SMSCode) GetUpdatedAt() time.Time {
|
||
|
|
return s.UpdatedAt
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate 验证短信验证码
|
||
|
|
func (s *SMSCode) Validate() error {
|
||
|
|
if s.Phone == "" {
|
||
|
|
return &ValidationError{Message: "手机号不能为空"}
|
||
|
|
}
|
||
|
|
if s.Code == "" {
|
||
|
|
return &ValidationError{Message: "验证码不能为空"}
|
||
|
|
}
|
||
|
|
if s.Scene == "" {
|
||
|
|
return &ValidationError{Message: "使用场景不能为空"}
|
||
|
|
}
|
||
|
|
if s.ExpiresAt.IsZero() {
|
||
|
|
return &ValidationError{Message: "过期时间不能为空"}
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// 业务方法
|
||
|
|
func (s *SMSCode) IsExpired() bool {
|
||
|
|
return time.Now().After(s.ExpiresAt)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *SMSCode) IsValid() bool {
|
||
|
|
return !s.Used && !s.IsExpired()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *SMSCode) MarkAsUsed() {
|
||
|
|
s.Used = true
|
||
|
|
now := time.Now()
|
||
|
|
s.UsedAt = &now
|
||
|
|
}
|
||
|
|
|
||
|
|
// TableName 指定表名
|
||
|
|
func (SMSCode) TableName() string {
|
||
|
|
return "sms_codes"
|
||
|
|
}
|