feat: add email_send_log table to track email sends and registration status
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,12 +21,14 @@ import (
|
||||
)
|
||||
|
||||
type UserService struct {
|
||||
userDao *dao.UserDao
|
||||
userDao *dao.UserDao
|
||||
emailSendLogDao *dao.EmailSendLogDao
|
||||
}
|
||||
|
||||
func NewUserService() *UserService {
|
||||
return &UserService{
|
||||
userDao: dao.NewUserDao(),
|
||||
userDao: dao.NewUserDao(),
|
||||
emailSendLogDao: dao.NewEmailSendLogDao(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +143,12 @@ func (svc *UserService) SendEmailVerifyCode(ctx context.Context, emailAddr strin
|
||||
if cacheErr := cache.SetUserSendEmailLimit(ctx, emailAddr); cacheErr != nil {
|
||||
log.Error(ctx, "func", "SendEmailVerifyCode", "msg", "set send email limit error", "error", cacheErr)
|
||||
}
|
||||
|
||||
record := &dao.EmailSendLog{Email: emailAddr, Status: dao.EmailSendStatusSent}
|
||||
if logErr := svc.emailSendLogDao.Create(dao.DB.WithContext(ctx), record); logErr != nil {
|
||||
log.Error(ctx, "func", "SendEmailVerifyCode", "msg", "create email send log error", "error", logErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -156,7 +164,16 @@ func (svc *UserService) RegisterByEmail(ctx context.Context, emailAddr, password
|
||||
|
||||
_ = cache.DeleteUserEmailCode(ctx, emailAddr)
|
||||
|
||||
return svc.registerByEmailInternal(ctx, emailAddr, password)
|
||||
uid, err = svc.registerByEmailInternal(ctx, emailAddr, password)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if logErr := svc.emailSendLogDao.MarkRegistered(dao.DB.WithContext(ctx), emailAddr); logErr != nil {
|
||||
log.Error(ctx, "func", "RegisterByEmail", "msg", "mark email send log registered error", "error", logErr)
|
||||
}
|
||||
|
||||
return uid, nil
|
||||
}
|
||||
|
||||
func (svc *UserService) registerByEmailInternal(ctx context.Context, emailAddr, password string) (uid int64, err error) {
|
||||
|
||||
50
internal/storage/dao/email_send_log.go
Normal file
50
internal/storage/dao/email_send_log.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type EmailSendStatus int8
|
||||
|
||||
const (
|
||||
EmailSendStatusSent EmailSendStatus = 0 // 已发送,用户未注册
|
||||
EmailSendStatusRegistered EmailSendStatus = 1 // 用户已完成注册
|
||||
)
|
||||
|
||||
type EmailSendLog struct {
|
||||
BaseModel
|
||||
Email string `gorm:"column:email;type:varchar(255);not null;comment:邮箱地址" json:"email"`
|
||||
Status EmailSendStatus `gorm:"column:status;type:tinyint;not null;default:0;comment:状态: 0=已发送未注册 1=已注册" json:"status"`
|
||||
}
|
||||
|
||||
func (e *EmailSendLog) TableName() string {
|
||||
return "email_send_log"
|
||||
}
|
||||
|
||||
type EmailSendLogDao struct{}
|
||||
|
||||
func NewEmailSendLogDao() *EmailSendLogDao {
|
||||
return &EmailSendLogDao{}
|
||||
}
|
||||
|
||||
func (d *EmailSendLogDao) Create(tx *gorm.DB, log *EmailSendLog) error {
|
||||
return tx.Create(log).Error
|
||||
}
|
||||
|
||||
func (d *EmailSendLogDao) GetLatestByEmail(tx *gorm.DB, email string) (*EmailSendLog, error) {
|
||||
var record EmailSendLog
|
||||
err := tx.Where("email = ?", email).Order("id DESC").First(&record).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &record, nil
|
||||
}
|
||||
|
||||
func (d *EmailSendLogDao) MarkRegistered(tx *gorm.DB, email string) error {
|
||||
return tx.Model(&EmailSendLog{}).
|
||||
Where("email = ? AND status = ?", email, EmailSendStatusSent).
|
||||
Update("status", EmailSendStatusRegistered).Error
|
||||
}
|
||||
11
migrations/email_send_log.sql
Normal file
11
migrations/email_send_log.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
CREATE TABLE IF NOT EXISTS `email_send_log` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`email` VARCHAR(255) NOT NULL COMMENT '邮箱地址',
|
||||
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态: 0=已发送未注册, 1=已注册',
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `idx_email` (`email`),
|
||||
INDEX `idx_status` (`status`),
|
||||
INDEX `idx_created_at` (`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='邮件发送记录表';
|
||||
Reference in New Issue
Block a user