mirror of https://github.com/veypi/OneAuth.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
67 lines
2.0 KiB
Go
67 lines
2.0 KiB
Go
|
1 week ago
|
//
|
||
|
|
// Copyright (C) 2024 veypi <i@veypi.com>
|
||
|
|
// 2025-03-04 16:08:06
|
||
|
|
// Distributed under terms of the MIT license.
|
||
|
|
//
|
||
|
|
|
||
|
|
package models
|
||
|
|
|
||
|
|
import (
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/veypi/vigo"
|
||
|
|
)
|
||
|
|
|
||
|
|
// VerificationCode 统一验证码表(邮箱 + 短信)
|
||
|
|
type VerificationCode struct {
|
||
|
|
vigo.Model
|
||
|
|
Target string `gorm:"index;size:100;not null" json:"target"` // 邮箱或手机号
|
||
|
|
Type string `gorm:"index;size:20;not null" json:"type"` // "email" | "sms"
|
||
|
|
Code string `gorm:"size:10;not null" json:"-"` // 验证码(不返回)
|
||
|
|
Purpose string `gorm:"index;size:20;not null" json:"purpose"` // register/login/reset_password/bind
|
||
|
|
Status CodeStatus `gorm:"default:0" json:"status"`
|
||
|
|
ExpiresAt time.Time `gorm:"index;not null" json:"expires_at"`
|
||
|
|
UsedAt *time.Time `json:"used_at"`
|
||
|
|
Attempts int `gorm:"default:0" json:"attempts"`
|
||
|
|
SendCount int `gorm:"default:1" json:"send_count"`
|
||
|
|
RemoteIP string `gorm:"size:50" json:"remote_ip"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// TableName 表名
|
||
|
|
func (VerificationCode) TableName() string {
|
||
|
|
return "verification_codes"
|
||
|
|
}
|
||
|
|
|
||
|
|
// CodeStatus 验证码状态
|
||
|
|
type CodeStatus int
|
||
|
|
|
||
|
|
const (
|
||
|
|
CodeStatusPending CodeStatus = iota // 待验证
|
||
|
|
CodeStatusUsed // 已使用
|
||
|
|
CodeStatusExpired // 已过期
|
||
|
|
CodeStatusFailed // 验证失败(超过最大尝试次数)
|
||
|
|
)
|
||
|
|
|
||
|
|
// IsExpired 检查验证码是否过期
|
||
|
|
func (c *VerificationCode) IsExpired() bool {
|
||
|
|
return time.Now().After(c.ExpiresAt)
|
||
|
|
}
|
||
|
|
|
||
|
|
// CanRetry 检查是否可以重试验证
|
||
|
|
func (c *VerificationCode) CanRetry(maxAttempts int) bool {
|
||
|
|
return c.Status == CodeStatusPending && c.Attempts < maxAttempts && !c.IsExpired()
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsUsed 检查是否已使用
|
||
|
|
func (c *VerificationCode) IsUsed() bool {
|
||
|
|
return c.Status == CodeStatusUsed && c.UsedAt != nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// 验证码用途常量
|
||
|
|
const (
|
||
|
|
CodePurposeRegister = "register"
|
||
|
|
CodePurposeLogin = "login"
|
||
|
|
CodePurposeResetPassword = "reset_password"
|
||
|
|
CodePurposeBind = "bind"
|
||
|
|
)
|