feat: persist huohanhan auth state in mysql

This commit is contained in:
QiuSW
2026-09-12 09:48:01 +08:00
parent 3803450e65
commit fe625aba61
2 changed files with 65 additions and 12 deletions
+6 -8
View File
@@ -11,7 +11,6 @@ import (
"go-admin/internal/config"
"go-admin/internal/huohanhan"
"go-admin/internal/logx"
"go-admin/internal/store"
"gorm.io/gorm"
"strings"
)
@@ -39,12 +38,16 @@ func (e ShopeeProduct) GetByShopeeID(c *gin.Context) {
e.Error(401, fmt.Errorf("invalid api key"), "未授权")
return
}
state, err := store.Open("temp/huohanhan-state.db")
db := primaryDB()
if db == nil {
e.Error(500, fmt.Errorf("database is not initialized"), "数据库未初始化")
return
}
state, err := huohanhan.NewMySQLStateStore(db)
if err != nil {
e.Error(500, err, "认证存储初始化失败")
return
}
defer state.Close()
cfg := config.HuohanhanConfig{BaseURL: ext.ExtConfig.Huohanhan.BaseURL, Account: ext.ExtConfig.Huohanhan.Account, Password: ext.ExtConfig.Huohanhan.Password, OCRURL: ext.ExtConfig.Huohanhan.OCRURL}
logger := logx.New(1000)
auth := huohanhan.NewAuthManager(cfg, state, logger, huohanhan.AuthOptions{})
@@ -83,11 +86,6 @@ func (e ShopeeProduct) GetByShopeeID(c *gin.Context) {
if v, ok := record["itemStatus"].(string); ok {
row.Status = v
}
db := primaryDB()
if db == nil {
e.Error(500, fmt.Errorf("database is not initialized"), "数据库未初始化")
return
}
if err = db.AutoMigrate(&models.ShopeeProduct{}); err != nil {
e.Error(500, err, "数据库初始化失败")
return
+59 -4
View File
@@ -16,6 +16,7 @@ import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"mime/multipart"
@@ -31,7 +32,7 @@ import (
"go-admin/internal/config"
"go-admin/internal/logx"
"go-admin/internal/store"
"gorm.io/gorm"
)
const (
@@ -71,6 +72,61 @@ type AuthState struct {
Cookies map[string]string `json:"cookies"`
}
// StateStore stores the serialized Huohanhan authentication state.
// The production adapter uses the GoAdmin MySQL database; the SQLite Store
// still satisfies this interface for isolated package tests and desktop tools.
type StateStore interface {
SetKV(key, value, now string) error
GetKV(key string) (string, bool, error)
}
type mysqlStateStore struct{ db *gorm.DB }
type mysqlStateRow struct {
Key string `gorm:"column:state_key;primaryKey;size:128"`
Value string `gorm:"column:state_value;type:longtext;not null"`
UpdatedAt string `gorm:"column:updated_at;size:64;not null"`
}
func (mysqlStateRow) TableName() string { return "huohanhan_auth_state" }
// NewMySQLStateStore creates a state store backed by the primary GoAdmin DB.
func NewMySQLStateStore(db *gorm.DB) (StateStore, error) {
if db == nil {
return nil, fmt.Errorf("数据库未初始化")
}
migrationErr := db.AutoMigrate(&mysqlStateRow{})
if migrationErr != nil {
return nil, fmt.Errorf("初始化货憨憨认证状态表失败:%v", migrationErr)
}
return mysqlStateStore{db: db}, nil
}
func (s mysqlStateStore) SetKV(key, value, now string) error {
var row mysqlStateRow
result := s.db.Where("state_key = ?", key).First(&row)
if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) {
return result.Error
}
row.Key, row.Value, row.UpdatedAt = key, value, now
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return s.db.Create(&row).Error
}
return s.db.Save(&row).Error
}
func (s mysqlStateStore) GetKV(key string) (string, bool, error) {
var row mysqlStateRow
err := s.db.Where("state_key = ?", key).First(&row).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return "", false, nil
}
if err != nil {
return "", false, err
}
return row.Value, true, nil
}
// AuthorizationValue 返回业务请求使用的 Authorization 值。
func (s AuthState) AuthorizationValue() string {
tokenType := strings.TrimSpace(s.TokenType)
@@ -92,7 +148,7 @@ func (s AuthState) Expired(now time.Time, skew time.Duration) bool {
// AuthManager 串行管理内存与 SQLite 中的认证状态。
type AuthManager struct {
cfg config.HuohanhanConfig
db *store.Store
db StateStore
log *logx.Logger
httpClient *http.Client
attempts int
@@ -104,7 +160,7 @@ type AuthManager struct {
}
// NewAuthManager 创建认证管理器。opts 的零值会补成默认配置。
func NewAuthManager(cfg config.HuohanhanConfig, db *store.Store, logger *logx.Logger, opts AuthOptions) *AuthManager {
func NewAuthManager(cfg config.HuohanhanConfig, db StateStore, logger *logx.Logger, opts AuthOptions) *AuthManager {
timeout := opts.RequestTimeout
if timeout <= 0 {
timeout = defaultRequestTimeout
@@ -653,4 +709,3 @@ func newUUID() (string, error) {
encoded := hex.EncodeToString(raw[:])
return encoded[0:8] + "-" + encoded[8:12] + "-" + encoded[12:16] + "-" + encoded[16:20] + "-" + encoded[20:32], nil
}