hi-server/internal/logic/public/user/emailTrialGrant.go
shanshanzhong 954b19c332
Some checks failed
Build docker and publish / build (20.15.1) (push) Has been cancelled
feat: 邮箱规范化(NormalizeEmail)与域名白名单检查(IsEmailDomainWhitelisted)
2026-04-12 18:43:47 -07:00

91 lines
2.6 KiB
Go

package user
import (
"context"
"time"
"github.com/perfect-panel/server/internal/logic/auth"
"github.com/perfect-panel/server/internal/model/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/tool"
"github.com/perfect-panel/server/pkg/uuidx"
)
func tryGrantTrialOnEmailBind(ctx context.Context, svcCtx *svc.ServiceContext, log logger.Logger, ownerUserId int64, email string) {
rc := svcCtx.Config.Register
if !auth.ShouldGrantTrialForEmail(rc, email) {
if rc.EnableTrial && rc.EnableTrialEmailWhitelist {
log.Infow("email domain not in trial whitelist, skip",
logger.Field("email", email),
logger.Field("owner_user_id", ownerUserId),
)
}
return
}
var count int64
if err := svcCtx.DB.WithContext(ctx).
Model(&user.Subscribe{}).
Where("user_id = ? AND subscribe_id = ?", ownerUserId, rc.TrialSubscribe).
Count(&count).Error; err != nil {
log.Errorw("failed to check existing trial", logger.Field("error", err.Error()))
return
}
if count > 0 {
log.Infow("trial already granted, skip",
logger.Field("owner_user_id", ownerUserId),
)
return
}
// Cross-user check: prevent the same real inbox (via dot trick / + alias) from
// getting multiple trials across different accounts.
if auth.NormalizedEmailHasTrial(ctx, svcCtx.DB, email, rc.TrialSubscribe) {
log.Infow("normalized email already has trial via another account, skip",
logger.Field("email", email),
logger.Field("owner_user_id", ownerUserId),
)
return
}
sub, err := svcCtx.SubscribeModel.FindOne(ctx, rc.TrialSubscribe)
if err != nil {
log.Errorw("failed to find trial subscribe template", logger.Field("error", err.Error()))
return
}
userSub := &user.Subscribe{
UserId: ownerUserId,
OrderId: 0,
SubscribeId: sub.Id,
StartTime: time.Now(),
ExpireTime: tool.AddTime(rc.TrialTimeUnit, rc.TrialTime, time.Now()),
Traffic: sub.Traffic,
Download: 0,
Upload: 0,
Token: uuidx.NewUUID().String(),
UUID: uuidx.NewUUID().String(),
Status: 1,
}
if err = svcCtx.UserModel.InsertSubscribe(ctx, userSub); err != nil {
log.Errorw("failed to insert trial subscribe",
logger.Field("error", err.Error()),
logger.Field("owner_user_id", ownerUserId),
)
return
}
if svcCtx.NodeModel != nil {
if err = svcCtx.NodeModel.ClearServerAllCache(ctx); err != nil {
log.Errorw("ClearServerAllCache error", logger.Field("error", err.Error()))
}
}
log.Infow("trial granted on email bind",
logger.Field("owner_user_id", ownerUserId),
logger.Field("email", email),
logger.Field("subscribe_id", sub.Id),
)
}