diff --git a/internal/logic/auth/emailLoginLogic.go b/internal/logic/auth/emailLoginLogic.go index 2392bee..4698d54 100644 --- a/internal/logic/auth/emailLoginLogic.go +++ b/internal/logic/auth/emailLoginLogic.go @@ -126,7 +126,9 @@ func (l *EmailLoginLogic) EmailLogin(req *types.EmailLoginRequest) (resp *types. return err } rc := l.svcCtx.Config.Register - if ShouldGrantTrialForEmail(rc, req.Email) && !NormalizedEmailHasTrial(l.ctx, l.svcCtx.DB, req.Email, rc.TrialSubscribe) { + if ShouldAutoGrantTrialOnPublicEmailFlows(rc) && + ShouldGrantTrialForEmail(rc, req.Email) && + !NormalizedEmailHasTrial(l.ctx, l.svcCtx.DB, req.Email, rc.TrialSubscribe) { if err = l.activeTrial(userInfo.Id); err != nil { return err } diff --git a/internal/logic/auth/oauth/oAuthLoginGetTokenLogic.go b/internal/logic/auth/oauth/oAuthLoginGetTokenLogic.go index c89273c..cc6a453 100644 --- a/internal/logic/auth/oauth/oAuthLoginGetTokenLogic.go +++ b/internal/logic/auth/oauth/oAuthLoginGetTokenLogic.go @@ -396,7 +396,10 @@ func (l *OAuthLoginGetTokenLogic) register(email, avatar, method, openid, reques } rc := l.svcCtx.Config.Register - shouldActivateTrial := email != "" && authlogic.ShouldGrantTrialForEmail(rc, email) && !authlogic.NormalizedEmailHasTrial(l.ctx, l.svcCtx.DB, email, rc.TrialSubscribe) + shouldActivateTrial := email != "" && + authlogic.ShouldAutoGrantTrialOnPublicEmailFlows(rc) && + authlogic.ShouldGrantTrialForEmail(rc, email) && + !authlogic.NormalizedEmailHasTrial(l.ctx, l.svcCtx.DB, email, rc.TrialSubscribe) if shouldActivateTrial { l.Debugw("activating trial subscription", diff --git a/internal/logic/auth/trialEmailWhitelist.go b/internal/logic/auth/trialEmailWhitelist.go index 019f995..8d9e6c3 100644 --- a/internal/logic/auth/trialEmailWhitelist.go +++ b/internal/logic/auth/trialEmailWhitelist.go @@ -54,6 +54,14 @@ func ShouldGrantTrialForEmail(register config.RegisterConfig, email string) bool return true } +// ShouldAutoGrantTrialOnPublicEmailFlows defines whether browser/email-originated +// flows may auto-create a trial subscription. The current policy disables trial +// creation for email registration, email login auto-register, OAuth-with-email, +// and email binding/verification to avoid abuse through public email channels. +func ShouldAutoGrantTrialOnPublicEmailFlows(register config.RegisterConfig) bool { + return false +} + // IsDisposableAlias detects Gmail dot trick and + alias abuse. // For Gmail-like domains, local part containing "." or "+" is rejected. // For all other domains, only "+" alias is rejected. diff --git a/internal/logic/auth/trialEmailWhitelist_test.go b/internal/logic/auth/trialEmailWhitelist_test.go index b5844b3..c4a8c0b 100644 --- a/internal/logic/auth/trialEmailWhitelist_test.go +++ b/internal/logic/auth/trialEmailWhitelist_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/perfect-panel/server/internal/config" + "github.com/stretchr/testify/assert" ) func TestNormalizeEmail(t *testing.T) { @@ -162,6 +163,15 @@ func TestShouldGrantTrialForEmail(t *testing.T) { } } +func TestShouldAutoGrantTrialOnPublicEmailFlows(t *testing.T) { + assert.False(t, ShouldAutoGrantTrialOnPublicEmailFlows(config.RegisterConfig{})) + assert.False(t, ShouldAutoGrantTrialOnPublicEmailFlows(config.RegisterConfig{ + EnableTrial: true, + EnableTrialEmailWhitelist: true, + TrialEmailDomainWhitelist: "gmail.com,example.com", + })) +} + func TestIsEmailDomainWhitelisted(t *testing.T) { whitelist := "gmail.com,edu.cn,outlook.com" tests := []struct { diff --git a/internal/logic/auth/userRegisterLogic.go b/internal/logic/auth/userRegisterLogic.go index 5fd97de..a5a0bf9 100644 --- a/internal/logic/auth/userRegisterLogic.go +++ b/internal/logic/auth/userRegisterLogic.go @@ -148,7 +148,9 @@ func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterRequest) (resp * // Activate trial subscription after transaction success (moved outside transaction to reduce lock time) rc := l.svcCtx.Config.Register - if ShouldGrantTrialForEmail(rc, req.Email) && !NormalizedEmailHasTrial(l.ctx, l.svcCtx.DB, req.Email, rc.TrialSubscribe) { + if ShouldAutoGrantTrialOnPublicEmailFlows(rc) && + ShouldGrantTrialForEmail(rc, req.Email) && + !NormalizedEmailHasTrial(l.ctx, l.svcCtx.DB, req.Email, rc.TrialSubscribe) { trialSubscribe, err = l.activeTrial(userInfo.Id) if err != nil { l.Errorw("Failed to activate trial subscription", logger.Field("error", err.Error())) diff --git a/internal/logic/public/user/emailTrialGrant.go b/internal/logic/public/user/emailTrialGrant.go index 602e0ad..530761b 100644 --- a/internal/logic/public/user/emailTrialGrant.go +++ b/internal/logic/public/user/emailTrialGrant.go @@ -14,6 +14,13 @@ import ( func tryGrantTrialOnEmailBind(ctx context.Context, svcCtx *svc.ServiceContext, log logger.Logger, ownerUserId int64, email string) { rc := svcCtx.Config.Register + if !auth.ShouldAutoGrantTrialOnPublicEmailFlows(rc) { + log.Infow("auto trial on email flow disabled, skip", + logger.Field("email", email), + logger.Field("owner_user_id", ownerUserId), + ) + return + } if !auth.ShouldGrantTrialForEmail(rc, email) { if rc.EnableTrial && rc.EnableTrialEmailWhitelist { log.Infow("email domain not in trial whitelist, skip",