Initial commit: 商品售卖网站
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"sale/internal/config"
|
||||
"sale/internal/models"
|
||||
|
||||
sqlite "github.com/glebarez/sqlite"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
var DB *gorm.DB
|
||||
|
||||
func InitDB() {
|
||||
var err error
|
||||
cfg := config.AppConfig.Database
|
||||
|
||||
switch cfg.Driver {
|
||||
case "mysql":
|
||||
dsn := fmt.Sprintf(
|
||||
"%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
||||
cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DBName,
|
||||
)
|
||||
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Info),
|
||||
})
|
||||
case "postgres":
|
||||
dsn := fmt.Sprintf(
|
||||
"host=%s port=%s user=%s password=%s dbname=%s sslmode=%s",
|
||||
cfg.Host, cfg.Port, cfg.User, cfg.Password, cfg.DBName, cfg.SSLMode,
|
||||
)
|
||||
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Info),
|
||||
})
|
||||
default:
|
||||
DB, err = gorm.Open(sqlite.Open(cfg.FilePath), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Info),
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to database: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Database connected successfully (driver: %s)", cfg.Driver)
|
||||
}
|
||||
|
||||
func AutoMigrate() {
|
||||
err := DB.AutoMigrate(
|
||||
&models.User{},
|
||||
&models.Category{},
|
||||
&models.Brand{},
|
||||
&models.Product{},
|
||||
&models.ProductCustomField{},
|
||||
&models.Inventory{},
|
||||
&models.Cart{},
|
||||
&models.Order{},
|
||||
&models.OrderItem{},
|
||||
&models.Address{},
|
||||
&models.Lottery{},
|
||||
&models.LotteryPrize{},
|
||||
&models.LotteryParticipant{},
|
||||
&models.LotteryWinner{},
|
||||
&models.Ticket{},
|
||||
&models.SystemSetting{},
|
||||
&models.SupplierAuthorization{},
|
||||
&models.Article{},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to migrate database: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Database migrated successfully")
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
|
||||
"sale/internal/config"
|
||||
)
|
||||
|
||||
func SendEmail(to, subject, body string) error {
|
||||
cfg := config.AppConfig.SMTP
|
||||
if cfg.Host == "" {
|
||||
return fmt.Errorf("SMTP not configured")
|
||||
}
|
||||
|
||||
auth := smtp.PlainAuth("", cfg.User, cfg.Password, cfg.Host)
|
||||
|
||||
msg := fmt.Sprintf(
|
||||
"From: %s\r\nTo: %s\r\nSubject: %s\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n%s",
|
||||
cfg.From, to, subject, body,
|
||||
)
|
||||
|
||||
return smtp.SendMail(
|
||||
fmt.Sprintf("%s:%s", cfg.Host, cfg.Port),
|
||||
auth,
|
||||
cfg.From,
|
||||
[]string{to},
|
||||
[]byte(msg),
|
||||
)
|
||||
}
|
||||
|
||||
func SendVerifyEmail(to, code string) error {
|
||||
subject := "邮箱验证码"
|
||||
body := fmt.Sprintf(`
|
||||
<h2>邮箱验证</h2>
|
||||
<p>您的验证码是:<strong style="font-size:24px;color:#1890ff;">%s</strong></p>
|
||||
<p>验证码有效期为30分钟,请尽快使用。</p>
|
||||
`, code)
|
||||
return SendEmail(to, subject, body)
|
||||
}
|
||||
|
||||
func SendResetPasswordEmail(to, code string) error {
|
||||
subject := "重置密码验证码"
|
||||
body := fmt.Sprintf(`
|
||||
<h2>重置密码</h2>
|
||||
<p>您的验证码是:<strong style="font-size:24px;color:#1890ff;">%s</strong></p>
|
||||
<p>验证码有效期为30分钟,请尽快使用。</p>
|
||||
`, code)
|
||||
return SendEmail(to, subject, body)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"sale/internal/config"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
UserID uint `json:"user_id"`
|
||||
Role string `json:"role"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func GenerateToken(userID uint, role string) (string, error) {
|
||||
claims := Claims{
|
||||
UserID: userID,
|
||||
Role: role,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(config.AppConfig.JWT.ExpireHour) * time.Hour)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(config.AppConfig.JWT.Secret))
|
||||
}
|
||||
|
||||
func ParseToken(tokenString string) (*Claims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(config.AppConfig.JWT.Secret), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("invalid token")
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func CheckPassword(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func GenerateInviteCode() string {
|
||||
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
code := make([]byte, 8)
|
||||
for i := range code {
|
||||
n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
|
||||
code[i] = charset[n.Int64()]
|
||||
}
|
||||
return string(code)
|
||||
}
|
||||
|
||||
func GenerateVerifyCode() string {
|
||||
const charset = "0123456789"
|
||||
code := make([]byte, 6)
|
||||
for i := range code {
|
||||
n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
|
||||
code[i] = charset[n.Int64()]
|
||||
}
|
||||
return string(code)
|
||||
}
|
||||
Reference in New Issue
Block a user