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 {
|
type UserService struct {
|
||||||
userDao *dao.UserDao
|
userDao *dao.UserDao
|
||||||
|
emailSendLogDao *dao.EmailSendLogDao
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserService() *UserService {
|
func NewUserService() *UserService {
|
||||||
return &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 {
|
if cacheErr := cache.SetUserSendEmailLimit(ctx, emailAddr); cacheErr != nil {
|
||||||
log.Error(ctx, "func", "SendEmailVerifyCode", "msg", "set send email limit error", "error", cacheErr)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +164,16 @@ func (svc *UserService) RegisterByEmail(ctx context.Context, emailAddr, password
|
|||||||
|
|
||||||
_ = cache.DeleteUserEmailCode(ctx, emailAddr)
|
_ = 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) {
|
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