diff --git a/cmd/test_db_insert/main.go b/cmd/test_db_insert/main.go new file mode 100644 index 0000000..dcfb542 --- /dev/null +++ b/cmd/test_db_insert/main.go @@ -0,0 +1,66 @@ +package main + +import ( + "context" + "fmt" + + "time" + + "github.com/perfect-panel/server/initialize" + "github.com/perfect-panel/server/internal/config" + loggerLog "github.com/perfect-panel/server/internal/model/log" + "github.com/perfect-panel/server/internal/svc" + "github.com/perfect-panel/server/pkg/conf" +) + +func main() { + var c config.Config + conf.MustLoad("etc/ppanel.yaml", &c) + + fmt.Println("Initializing ServiceContext...") + svcCtx := svc.NewServiceContext(c) + initialize.Email(svcCtx) + fmt.Println("ServiceContext initialized.") + + ctx := context.Background() + + // 模拟真实数据 + content := map[string]interface{}{ + "Type": 1, + "SiteLogo": c.Site.SiteLogo, + "SiteName": c.Site.SiteName, + "Expire": 15, + "Code": "123456", + } + + messageLog := loggerLog.Message{ + Platform: svcCtx.Config.Email.Platform, + To: "shanshanzhong147@gmail.com", + Subject: "PPanel Test - Verify Email (Register)", + Content: content, + Status: 1, + } + + emailLog, err := messageLog.Marshal() + if err != nil { + panic(err) + } + + systemLog := &loggerLog.SystemLog{ + Type: loggerLog.TypeEmailMessage.Uint8(), + Date: time.Now().Format("2006-01-02"), + ObjectID: 0, + Content: string(emailLog), + } + + fmt.Println("Attempting to insert into system_logs...") + err = svcCtx.LogModel.Insert(ctx, systemLog) + if err != nil { + fmt.Printf("❌ Insert failed!\n") + fmt.Printf("Error Type: %T\n", err) + fmt.Printf("Error String: %s\n", err.Error()) + fmt.Printf("Detailed Error: %+v\n", err) + } else { + fmt.Println("✅ Insert successful!") + } +} diff --git a/cmd/test_email/main.go b/cmd/test_email/main.go new file mode 100644 index 0000000..89c5709 --- /dev/null +++ b/cmd/test_email/main.go @@ -0,0 +1,119 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + + "github.com/hibiken/asynq" + "github.com/perfect-panel/server/initialize" + "github.com/perfect-panel/server/internal/config" + "github.com/perfect-panel/server/internal/svc" + "github.com/perfect-panel/server/pkg/conf" + emailLogic "github.com/perfect-panel/server/queue/logic/email" + "github.com/perfect-panel/server/queue/types" +) + +func main() { + var c config.Config + conf.MustLoad("etc/ppanel.yaml", &c) + + if !c.Email.Enable { + log.Fatal("Email is disabled in config. Please enable it in etc/ppanel.yaml") + } + + // Initialize ServiceContext + svcCtx := svc.NewServiceContext(c) + initialize.Email(svcCtx) + ctx := context.Background() + + // Target email + targetEmail := "shanshanzhong147@gmail.com" + fmt.Printf("Preparing to send emails to: %s\n", targetEmail) + + senderLogic := emailLogic.NewSendEmailLogic(svcCtx) + + // 1. Verify Email (Register) + fmt.Println("\n[1/5] Sending Registration/Verify Email...") + send(ctx, senderLogic, types.SendEmailPayload{ + Type: types.EmailTypeVerify, + Email: targetEmail, + Subject: "PPanel Test - Verify Email (Register)", + Content: map[string]interface{}{ + "Type": 1, // 1: Register + "SiteLogo": c.Site.SiteLogo, + "SiteName": c.Site.SiteName, + "Expire": 15, + "Code": "123456", + }, + }) + + // 2. Verify Email (Password Reset) + fmt.Println("\n[2/5] Sending Password Reset/Verify Email...") + send(ctx, senderLogic, types.SendEmailPayload{ + Type: types.EmailTypeVerify, + Email: targetEmail, + Subject: "PPanel Test - Verify Email (Password Reset)", + Content: map[string]interface{}{ + "Type": 2, // 2: Password Reset + "SiteLogo": c.Site.SiteLogo, + "SiteName": c.Site.SiteName, + "Expire": 15, + "Code": "654321", + }, + }) + + // 3. Maintenance Email + fmt.Println("\n[3/5] Sending Maintenance Email...") + send(ctx, senderLogic, types.SendEmailPayload{ + Type: types.EmailTypeMaintenance, + Email: targetEmail, + Subject: "PPanel Test - Maintenance Notice", + Content: map[string]interface{}{ + "SiteLogo": c.Site.SiteLogo, + "SiteName": c.Site.SiteName, + "MaintenanceDate": "2026-01-01", + "MaintenanceTime": "12:00 - 14:00 (UTC+8)", + }, + }) + + // 4. Expiration Email + fmt.Println("\n[4/5] Sending Expiration Email...") + send(ctx, senderLogic, types.SendEmailPayload{ + Type: types.EmailTypeExpiration, + Email: targetEmail, + Subject: "PPanel Test - Subscription Expiration", + Content: map[string]interface{}{ + "SiteLogo": c.Site.SiteLogo, + "SiteName": c.Site.SiteName, + "ExpireDate": "2026-02-01", + }, + }) + + // 5. Traffic Exceed Email + fmt.Println("\n[5/5] Sending Traffic Exceed Email...") + send(ctx, senderLogic, types.SendEmailPayload{ + Type: types.EmailTypeTrafficExceed, + Email: targetEmail, + Subject: "PPanel Test - Traffic Exceeded", + Content: map[string]interface{}{ + "SiteLogo": c.Site.SiteLogo, + "SiteName": c.Site.SiteName, + "UsedTraffic": "100GB", + "MaxTraffic": "100GB", + }, + }) + + fmt.Println("\nAll tests completed. Please check your inbox.") +} + +func send(ctx context.Context, l *emailLogic.SendEmailLogic, payload types.SendEmailPayload) { + data, _ := json.Marshal(payload) + task := asynq.NewTask(types.ForthwithSendEmail, data) + if err := l.ProcessTask(ctx, task); err != nil { + fmt.Printf("❌ Failed to send %s: %v\n", payload.Type, err) + } else { + fmt.Printf("✅ Sent %s successfully.\n", payload.Type) + } +} diff --git a/docs/设备移出和邀请码优化/aaa.txt b/docs/设备移出和邀请码优化/aaa.txt new file mode 100644 index 0000000..e69de29 diff --git a/initialize/migrate/database/02123_update_auth_method_config.down.sql b/initialize/migrate/database/02123_update_auth_method_config.down.sql new file mode 100644 index 0000000..07c57f1 --- /dev/null +++ b/initialize/migrate/database/02123_update_auth_method_config.down.sql @@ -0,0 +1 @@ +ALTER TABLE auth_method MODIFY config TEXT NOT NULL COMMENT 'Auth Configuration'; diff --git a/initialize/migrate/database/02123_update_auth_method_config.up.sql b/initialize/migrate/database/02123_update_auth_method_config.up.sql new file mode 100644 index 0000000..ea3d7fb --- /dev/null +++ b/initialize/migrate/database/02123_update_auth_method_config.up.sql @@ -0,0 +1 @@ +ALTER TABLE auth_method MODIFY config MEDIUMTEXT NOT NULL COMMENT 'Auth Configuration'; diff --git a/internal/logic/public/user/unbindDeviceLogic.go b/internal/logic/public/user/unbindDeviceLogic.go index 745403a..be743c9 100644 --- a/internal/logic/public/user/unbindDeviceLogic.go +++ b/internal/logic/public/user/unbindDeviceLogic.go @@ -124,6 +124,8 @@ func (l *UnbindDeviceLogic) UnbindDevice(req *types.UnbindDeviceRequest) error { _ = l.svcCtx.Redis.ZRem(ctx, sessionsKey, sessionId).Err() } l.svcCtx.DeviceManager.KickDevice(u.Id, identifier) + // clean user cache + _ = l.svcCtx.UserModel.ClearUserCache(l.ctx, u) l.Infow("设备解绑完成", logger.Field("device_identifier", identifier), logger.Field("elapsed_ms", duration.Milliseconds())) diff --git a/internal/model/auth/auth.go b/internal/model/auth/auth.go index f85070c..a697947 100644 --- a/internal/model/auth/auth.go +++ b/internal/model/auth/auth.go @@ -10,7 +10,7 @@ import ( type Auth struct { Id int64 `gorm:"primaryKey"` Method string `gorm:"unique;type:varchar(255);not null;default:'';comment:platform"` - Config string `gorm:"type:text;not null;comment:Auth Configuration"` + Config string `gorm:"type:mediumtext;not null;comment:Auth Configuration"` Enabled *bool `gorm:"type:tinyint(1);not null;default:false;comment:Is Enabled"` CreatedAt time.Time `gorm:"<-:create;comment:Create Time"` UpdatedAt time.Time `gorm:"comment:Update Time"` @@ -129,7 +129,7 @@ func (l *EmailAuthConfig) Marshal() string { if l.ExpirationEmailTemplate == "" { l.ExpirationEmailTemplate = email.DefaultExpirationEmailTemplate } - if l.ExpirationEmailTemplate == "" { + if l.MaintenanceEmailTemplate == "" { l.MaintenanceEmailTemplate = email.DefaultMaintenanceEmailTemplate } if l.TrafficExceedEmailTemplate == "" { @@ -175,6 +175,19 @@ func (l *EmailAuthConfig) Unmarshal(data string) { } _ = json.Unmarshal([]byte(config.Marshal()), &l) } + + if l.ExpirationEmailTemplate == "" { + l.ExpirationEmailTemplate = email.DefaultExpirationEmailTemplate + } + if l.MaintenanceEmailTemplate == "" { + l.MaintenanceEmailTemplate = email.DefaultMaintenanceEmailTemplate + } + if l.TrafficExceedEmailTemplate == "" { + l.TrafficExceedEmailTemplate = email.DefaultTrafficExceedEmailTemplate + } + if l.VerifyEmailTemplate == "" { + l.VerifyEmailTemplate = email.DefaultEmailVerifyTemplate + } } // SMTPConfig Email SMTP configuration