Initial commit: 网络验证平台

This commit is contained in:
Admin
2026-04-27 17:22:56 +08:00
commit afe67d704e
780 changed files with 88960 additions and 0 deletions
+481
View File
@@ -0,0 +1,481 @@
package developer
import (
"fmt"
"math/rand"
"time"
"verification-platform-backend/internal/database"
"verification-platform-backend/internal/model"
"verification-platform-backend/internal/service"
"verification-platform-backend/pkg/response"
"github.com/gin-gonic/gin"
)
func SetupEmailRoutes(r *gin.RouterGroup) {
r.GET("/applications/:id/email-config", handleGetEmailConfig)
r.PUT("/applications/:id/email-config", handleUpdateEmailConfig)
r.POST("/applications/:id/email-config/test", handleTestEmailConfig)
r.GET("/applications/:id/email-templates", handleGetEmailTemplates)
r.GET("/applications/:id/email-templates/:template_id", handleGetEmailTemplate)
r.POST("/applications/:id/email-templates", handleCreateEmailTemplate)
r.PUT("/applications/:id/email-templates/:template_id", handleUpdateEmailTemplate)
r.DELETE("/applications/:id/email-templates/:template_id", handleDeleteEmailTemplate)
r.POST("/applications/:id/send-verify-code", handleSendVerifyCode)
}
func handleGetEmailConfig(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var permission model.PackagePermission
hasPermission := checkEmailPermission(userID.(uint), &permission)
if !hasPermission {
response.Error(c, 403, "您的套餐不支持邮件功能")
return
}
var smtpConfig model.AppSMTPConfig
database.DB.Where("application_id = ?", app.ID).First(&smtpConfig)
result := gin.H{
"enable_email_verify": app.EnableEmailVerify,
"require_email_verify": app.RequireEmailVerify,
"enable_password_reset": app.EnablePasswordReset,
"permission": gin.H{
"allow_email": permission.AllowEmail,
},
}
if smtpConfig.ID > 0 {
result["smtp_config"] = gin.H{
"id": smtpConfig.ID,
"host": smtpConfig.Host,
"port": smtpConfig.Port,
"user": smtpConfig.User,
"from_name": smtpConfig.FromName,
"from_email": smtpConfig.FromEmail,
"use_ssl": smtpConfig.UseSSL,
"status": smtpConfig.Status,
}
} else {
result["smtp_config"] = nil
}
response.Success(c, result)
}
func handleUpdateEmailConfig(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var permission model.PackagePermission
hasPermission := checkEmailPermission(userID.(uint), &permission)
if !hasPermission {
response.Error(c, 403, "您的套餐不支持邮件功能")
return
}
var req struct {
EnableEmailVerify bool `json:"enable_email_verify"`
RequireEmailVerify bool `json:"require_email_verify"`
EnablePasswordReset bool `json:"enable_password_reset"`
SMTPConfig *struct {
Host string `json:"host"`
Port int `json:"port"`
User string `json:"user"`
Password string `json:"password"`
FromName string `json:"from_name"`
FromEmail string `json:"from_email"`
UseSSL bool `json:"use_ssl"`
} `json:"smtp_config"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
updates := map[string]interface{}{
"enable_email_verify": req.EnableEmailVerify,
"require_email_verify": req.RequireEmailVerify,
"enable_password_reset": req.EnablePasswordReset,
}
if err := database.DB.Model(&app).Updates(updates).Error; err != nil {
response.Error(c, 500, "更新失败")
return
}
if req.SMTPConfig != nil {
var smtpConfig model.AppSMTPConfig
database.DB.Where("application_id = ?", app.ID).First(&smtpConfig)
smtpConfig.ApplicationID = app.ID
smtpConfig.Host = req.SMTPConfig.Host
smtpConfig.Port = req.SMTPConfig.Port
smtpConfig.User = req.SMTPConfig.User
if req.SMTPConfig.Password != "" {
smtpConfig.Password = req.SMTPConfig.Password
}
smtpConfig.FromName = req.SMTPConfig.FromName
smtpConfig.FromEmail = req.SMTPConfig.FromEmail
smtpConfig.UseSSL = req.SMTPConfig.UseSSL
if smtpConfig.ID > 0 {
database.DB.Save(&smtpConfig)
} else {
database.DB.Create(&smtpConfig)
}
}
response.Success(c, gin.H{
"message": "更新成功",
})
}
func handleTestEmailConfig(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var req struct {
Email string `json:"email" binding:"required,email"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "请输入有效的邮箱地址")
return
}
var smtpConfig model.AppSMTPConfig
if err := database.DB.Where("application_id = ?", app.ID).First(&smtpConfig).Error; err != nil {
response.Error(c, 400, "请先配置SMTP")
return
}
emailService := service.NewEmailService()
config := service.EmailConfig{
Host: smtpConfig.Host,
Port: smtpConfig.Port,
User: smtpConfig.User,
Password: smtpConfig.Password,
FromName: smtpConfig.FromName,
FromEmail: smtpConfig.FromEmail,
UseSSL: smtpConfig.UseSSL,
}
if err := emailService.SendTestEmail(config, req.Email, app.Name); err != nil {
response.Error(c, 500, fmt.Sprintf("发送失败: %v", err))
return
}
response.Success(c, gin.H{
"message": "测试邮件已发送",
})
}
func handleGetEmailTemplates(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var permission model.PackagePermission
hasPermission := checkEmailPermission(userID.(uint), &permission)
if !hasPermission {
response.Error(c, 403, "您的套餐不支持邮箱验证功能")
return
}
var templates []model.EmailTemplate
database.DB.Where("application_id = ?", app.ID).Order("created_at DESC").Find(&templates)
response.Success(c, templates)
}
func handleGetEmailTemplate(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
templateID := c.Param("template_id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var template model.EmailTemplate
if err := database.DB.Where("id = ? AND application_id = ?", templateID, app.ID).First(&template).Error; err != nil {
response.Error(c, 404, "模板不存在")
return
}
response.Success(c, template)
}
func handleCreateEmailTemplate(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var permission model.PackagePermission
hasPermission := checkEmailPermission(userID.(uint), &permission)
if !hasPermission {
response.Error(c, 403, "您的套餐不支持邮件功能")
return
}
var req struct {
Type string `json:"type" binding:"required"`
Name string `json:"name" binding:"required"`
Subject string `json:"subject" binding:"required"`
Content string `json:"content" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
template := model.EmailTemplate{
ApplicationID: app.ID,
Type: req.Type,
Name: req.Name,
Subject: req.Subject,
Content: req.Content,
Status: "active",
}
if err := database.DB.Create(&template).Error; err != nil {
response.Error(c, 500, "创建失败")
return
}
response.Success(c, template)
}
func handleUpdateEmailTemplate(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
templateID := c.Param("template_id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var permission model.PackagePermission
hasPermission := checkEmailPermission(userID.(uint), &permission)
if !hasPermission {
response.Error(c, 403, "您的套餐不支持邮件功能")
return
}
var template model.EmailTemplate
if err := database.DB.Where("id = ? AND application_id = ?", templateID, app.ID).First(&template).Error; err != nil {
response.Error(c, 404, "模板不存在")
return
}
var req struct {
Type string `json:"type"`
Name string `json:"name"`
Subject string `json:"subject"`
Content string `json:"content"`
Status string `json:"status"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
updates := map[string]interface{}{}
if req.Type != "" {
updates["type"] = req.Type
}
if req.Name != "" {
updates["name"] = req.Name
}
if req.Subject != "" {
updates["subject"] = req.Subject
}
if req.Content != "" {
updates["content"] = req.Content
}
if req.Status != "" {
updates["status"] = req.Status
}
if err := database.DB.Model(&template).Updates(updates).Error; err != nil {
response.Error(c, 500, "更新失败")
return
}
response.Success(c, template)
}
func handleDeleteEmailTemplate(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
templateID := c.Param("template_id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var permission model.PackagePermission
hasPermission := checkEmailPermission(userID.(uint), &permission)
if !hasPermission {
response.Error(c, 403, "您的套餐不支持邮件功能")
return
}
if err := database.DB.Where("id = ? AND application_id = ?", templateID, app.ID).Delete(&model.EmailTemplate{}).Error; err != nil {
response.Error(c, 500, "删除失败")
return
}
response.Success(c, gin.H{
"message": "删除成功",
})
}
func handleSendVerifyCode(c *gin.Context) {
userID, _ := c.Get("user_id")
appID := c.Param("id")
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", appID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var req struct {
Email string `json:"email" binding:"required,email"`
Purpose string `json:"purpose"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "请输入有效的邮箱地址")
return
}
if req.Purpose == "" {
req.Purpose = "register"
}
var smtpConfig model.AppSMTPConfig
if err := database.DB.Where("application_id = ?", app.ID).First(&smtpConfig).Error; err != nil {
response.Error(c, 400, "请先配置SMTP")
return
}
var template model.EmailTemplate
database.DB.Where("application_id = ? AND type = ? AND status = ?", app.ID, req.Purpose, "active").
Order("is_default DESC").First(&template)
code := generateVerifyCode()
expireAt := time.Now().Add(15 * time.Minute)
verifyCode := model.EmailVerifyCode{
ApplicationID: app.ID,
Email: req.Email,
Code: code,
Purpose: req.Purpose,
ExpiresAt: expireAt,
}
database.DB.Create(&verifyCode)
emailService := service.NewEmailService()
config := service.EmailConfig{
Host: smtpConfig.Host,
Port: smtpConfig.Port,
User: smtpConfig.User,
Password: smtpConfig.Password,
FromName: smtpConfig.FromName,
FromEmail: smtpConfig.FromEmail,
UseSSL: smtpConfig.UseSSL,
}
subject := fmt.Sprintf("验证码 - %s", app.Name)
content := fmt.Sprintf(`
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"></head>
<body style="font-family: Arial, sans-serif; padding: 20px; background-color: #f5f5f5;">
<div style="max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<h2 style="color: #333; margin-bottom: 20px;">邮箱验证</h2>
<p style="color: #666; line-height: 1.6;">您的验证码是:<strong style="font-size: 24px; color: #1890ff;">%s</strong></p>
<p style="color: #999; font-size: 12px;">验证码有效期为15分钟,请尽快使用。</p>
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
<p style="color: #999; font-size: 12px;">此邮件由 %s 系统自动发送,请勿回复。</p>
</div>
</body>
</html>
`, code, app.Name)
if template.ID > 0 {
subject = template.Subject
content = template.Content
}
if err := emailService.SendEmail(config, req.Email, subject, content); err != nil {
response.Error(c, 500, fmt.Sprintf("发送失败: %v", err))
return
}
response.Success(c, gin.H{
"message": "验证码已发送",
})
}
func checkEmailPermission(userID uint, permission *model.PackagePermission) bool {
var userPackage model.UserPackage
if err := database.DB.Where("user_id = ? AND status = ?", userID, "active").
Preload("Package").First(&userPackage).Error; err != nil {
return false
}
if userPackage.ExpiredAt != nil && userPackage.ExpiredAt.Before(time.Now()) {
return false
}
if err := database.DB.Where("package_id = ?", userPackage.PackageID).First(permission).Error; err != nil {
return false
}
return permission.AllowEmail
}
func generateVerifyCode() string {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
return fmt.Sprintf("%06d", r.Intn(1000000))
}